Inno Setup:在 [运行] 部分执行 Pascal 函数

Inno Setup: Execute a Pascal function in [Run] section

在安装结束时,我需要 运行 更新飞行模拟器 .cfg 文件(在 Inno Setup 中称为 .ini 文件)的 Pascal 函数。 Pascal 函数存在于其 [Code] 部分并且 运行s 是正确的。我想 运行 [Run] 部分中的这个 Pascal 函数使用 StatusMsg 来告诉用户发生了什么。

[Run]
Filename: {code:FsxEditSceneryFile|Add#<scenerySpec>}; StatusMsg: "Add scenery to FSX";
; <scenerySpec> is just a place holder of the actual scenery specification!

除 Inno Setup 强制我使用 string 作为 Pascal 函数的 return 值外,一切都按预期工作。然而,Filename 语句需要一个 Boolean 作为 return 值来指定执行是成功 (True) 还是失败 (False)。这种类型不匹配会在 Filename 语句执行结束时产生一个错误消息框,说

CreateProcess failed; Code 87. Wrong Parameter.

任何建议如何解决这个问题?我知道存在我可以使用的事件函数,例如CurStepChanged() 但我发现 StatusMsg 机制非常好,可以告诉用户安装完成了什么。

您正在滥用 Filename 参数解析来执行某些代码。解析参数值时未记录。这使您的方法不可靠。在显示 StatusMsg 时,您无法知道该值已解析。此外,该值无论如何都必须解析为可执行路径。 Inno Setup 将尝试执行它(因此出现错误)。你可能不想要什么。不要那样做。


相反,正如您已经建议的,使用 CurStepChanged。您可以通过访问 WizardForm.StatusLabel.

来显示来自 Pascal 代码的状态消息
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    WizardForm.StatusLabel.Caption := 'Installing something...';
    { Install something }
  end;
end;

万一其他人遇到这个问题,这里有一个解决方案,可以让您 运行 Pascal 脚本程序“就地”在 [RUN] 部分中的任何语句。

我需要将 powershell 脚本的执行移动到 [CODE] 部分,因为 [RUN] 部分不提供对外部 cmd 程序的退出代码做出反应的方法。 因为我有一堆子安装程序,我需要在我的设置中以特定顺序执行,所以可以选择控制 [RUN] 部分中 pascal 脚本的位置,而不仅仅是何时进入 [运行] 部分设置步骤。

它的工作原理是使用“虚拟”程序(如 ping)作为 [RUN] 语句的文件名,然后使用内置的 BeforeInstall 参数调用 pascal 脚本包含实际执行逻辑的过程。

[运行]节

Filename: "ping"; BeforeInstall: RunSQLSetupScript; Components: "thirds\db"; StatusMsg: "Installing SQL Server ..." ; Flags: runhidden

包含实际执行逻辑的 Pascal 脚本程序

(请注意,{tmp}\{#SQLServerInstallScript} 将是此示例中脚本的实际路径,因为通常建议避免硬编码路径并改用常量 + 临时目录。)

//  runs the SQL setup script and terminates the setup process, if the script returns an exit code that indicates an error
procedure RunSQLSetupScript();
var
  runSuccess: Boolean;
  retVar: Integer;
  msgText: String;
begin
  runSuccess := ShellExec('', 'powershell.exe', '-NoProfile -File ' + ExpandConstant('{tmp}\{#SQLServerInstallScript}'), '', SW_SHOW, ewWaitUntilTerminated, retVar);
      
  // the external script will return an exit code > 0 if an error occurred
  if (runSuccess = False) or (retVar > 0) then
  begin
    msgText := 'SQL Server setup script returned error code ' + IntToStr(retVar) + ', indicating an unsuccessful installation of SQL Server. Setup will now terminate.';
     
    MsgBox(msgText, mbCriticalError, MB_OK);
    // => further handle error case here, like cancelling the running setup or log the issue etc.
  end;
end;