Inno Setup 根据所选组件更改 AppName

Inno Setup Change AppName based on component(s) selected

我需要安装程序根据(未)选择的组件显示不同的 AppName。我试过这个:

[Setup]
AppName={code:GetAppName}
AppVersion=1.0
AppVerName=Dagon Video Tools
AppId=Dagon Video Tools
DefaultDirName={sd}\Games\Dagon Video Tools

[Code]
function GetAppName(Value: string): string;
var
  CurPageID: Integer;
Begin
  Result := 'Dagon Video Tools'
  if (CurPageID=wpSelectComponents) and IsComponentSelected('Slasher') and not IsComponentSelected('Frankenstein') then
    begin
      Result := 'Dagon Slasher';
    end;
  if (CurPageID=wpSelectComponents) and IsComponentSelected('Frankenstein') and not IsComponentSelected('Slasher') then
    begin
      Result := 'Dagon Frankenstein';
    end;
  if (CurPageID=wpSelectComponents) and IsComponentSelected('Slasher') and IsComponentSelected('Frankenstein') then
    begin
      Result := 'Dagon Video Tools';
    end;
End;

但是,如您所料,这是行不通的。这个脚本是不完整的还是应该以完全不同的方式完成?

The AppName directive value is resolved (= your GetAppName is called) immediately after the InitializeSetup(如果有)完成。那是在用户能够更改组件之前很久。

所以你不能AppName依赖于所选组件。

AppName 的某些用途可以用自定义值覆盖,但不是全部。 见下文。


不过,据我所知,您的问题实际上是关于设置类型的,您可以这样做:

  • 创建自定义 "type" 页面(如菜单)作为第一个页面。
  • 用户选择 "type" 后,使用自定义开关(例如 /APPTYPE=slasher)重新启动安装程序并退出。
  • 一旦安装程序(重新)运行 /APPTYPE,您从一开始就知道您正在安装什么 component/type,因此您可以设置 AppName正常。
  • 当然,您跳过自定义 "type" 页面。

这其实是一种更容易实现的方式。唯一的缺点是用户选择"type"后设置window是"recreated"。


如果您不想使用上述解决方案,这是原始回复。

首先,您对 GetAppName 的实施是错误的。您正在使用未初始化的变量 CurPageID。无论如何,如前所述,GetAppName 甚至在创建向导 window 之前就已被调用,因此 "current page" 与此处无关。

正确的实现应该是这样的:

function GetAppName(Value: string): string;
begin
  if IsComponentSelected('Slasher') and not IsComponentSelected('Frankenstein') then
  begin
    Result := 'Dagon Slasher';
  end
    else
  if IsComponentSelected('Frankenstein') and not IsComponentSelected('Slasher') then
  begin
    Result := 'Dagon Frankenstein';
  end
    else
  begin
    Result := 'Dagon Video Tools';
  end;
end;

但这仍然不能使它在 AppName 指令中工作。我们稍后会在其他情况下使用它。

另请注意,对于 , you should better use the WizardSetupType(false) function 而不是 IsComponentSelected


完成标签

只需覆盖 CurPageChanged(wpFinished) 中的 Inno Setup 默认文本:

procedure CurPageChanged(CurPageID: Integer);
var
  S: string;
begin
  if CurPageID = wpFinished then
  begin
    S := SetupMessage(msgFinishedHeadingLabel);
    StringChange(S, '[name]', GetAppName(''));
    WizardForm.FinishedHeadingLabel.Caption := S;
    WizardForm.AdjustLabelHeight(WizardForm.FinishedHeadingLabel);
    { Ideally we should shift the FinishedLabel up or down here, }
    { if the height of the header changed. }

    { Note that other messages (msgFinishedLabelNoIcons or msgFinishedRestartLabel) }
    { are used in special situations, so this is not a complete solution. }
    S := SetupMessage(msgFinishedLabel);
    StringChange(S, '[name]', GetAppName(''));
    WizardForm.FinishedLabel.Caption := S;
    WizardForm.AdjustLabelHeight(WizardForm.FinishedLabel);
  end;
end;

Add/Remove 程序

这很简单。为此有 the UninstallDisplayName directive,只有在实际安装期间我们已经知道所选组件时才会解决。所以我们可以在这里使用你的(固定的)GetAppName

[Setup]
UninstallDisplayName={code:GetAppName}

您确定要完全删除 AppName 及其所有组件吗?

你不能改变它。您最好在 AppName 中使用一些通用名称,以便此消息适用于任何组件。

或者让消息完全不提及应用程序名称:

[Messages]
ConfirmUninstall=Are you sure you want to completely remove this game?

或者完全删除消息:


正在从您的计算机中删除 AppName,请稍候

WizardForm.FinishedLabel 相同的解决方案。只需使用 the InitializeUninstallProgressForm.

中的 UninstallProgressForm.PageDescriptionLabel

AppName 已成功从您的计算机中删除

类似于 "Are you sure you want to completely remove AppName and all of its components?"

要么使 AppName 通用。或者使用 "silent" 模式禁用消息并在 the CurUninstallStepChanged(usPostUninstall) 中实现您自己的消息。 再次参见


有关类似的讨论,另请参阅 Changing AppName and AppDir depending on language in Inno Setup