Inno Setup 中的 msi 返回代码

发布于 2024-07-14 06:46:53 字数 128 浏览 4 评论 0原文

我想以静默模式调用多个 .msi 文件,并在任何失败时停止整个安装。

是否可以获取从 [run] 部分调用 msiexec.exe 的返回代码?

目前我只能在 Windows 事件查看器中看到错误消息。

I would like to call multiple .msi files in silent mode, and halt the entire installation if any fail.

Is it possible to get the return codes of msiexec.exe being called from the [run] section?

Currently I can only see error messages in the windows event viewer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟酉 2024-07-21 06:46:53

目前无法检查[Run]条目是否成功执行。 该代码只是记录进程退出代码并继续执行下一个条目(可以在 Inno Setup 源文件 Main.pas 中查看,函数为 ProcessRunEntry(),从当前版本 5.2.3 中的第 3404 行开始)。

如果您需要确保 msiexec 的多次执行均成功,则需要编写中间层。 这可以像在 [Run] 条目中执行的一个小存根一样简单,并使用正确的参数启动 msiexec.exe,等待进程完成,然后将返回代码写入文件。

检查此类安装步骤是否成功的另一种方法是使用 AfterInstall 参数为每​​个 [Run] 条目添加自定义过程调用。 在这样的函数中,您可以例如检查 OCX 控件是否已成功安装:

[Run]
Filename: "{tmp}\MyInstallation1.exe"; Parameters: "/foo"; AfterInstall: AfterMyInstallation1

[Code]
var
  MyInstallation1Success: boolean;

procedure AfterMyInstallation1;
var
  V: Variant;
begin
  try
    V := CreateOleObject('MyInstallation.InstalledOcxControl.1');
    MyInstallation1Success := True;
  except
    MyInstallation1Success := False;
  end;
end;

或者依赖项的目录和注册表项是否都在那里。

每个[Run]条目仅在其可选的Check参数确实返回true时执行。 因此,根据您的需要,您可以依次启动所有静默安装,并在最后一个安装完成后执行脚本函数来检查所有依赖项是否已成功安装; 或者您可以为每个依赖项安装编写一个检查函数,该函数将返回 false,从而在第一个失败的安装之后跳过所有其他安装。

但请注意,所有[运行]条目都是在文件复制、注册表写入等步骤完成后执行的,因此您基本上已经完成了安装。 如果您只想在正确安装所有依赖项后才真正执行所有安装步骤,那么您必须在该过程的早期执行此操作,此时安装仍然可以取消。

编辑:查看问题“如何让 Inno Setup 在执行长 Exec 时看起来不被冻结?” 其中给出了一些信息,并链接了一个关于使用 Exec( ) 用于安装依赖项的函数。 因此,如果您不使用[Run]条目,则很有可能实现您想要的目标。

There is currently no way to check the successful execution of [Run] entries. The code just logs the process exit code and continues with the next entry (it can be examined in the Inno Setup source file Main.pas, the function is ProcessRunEntry(), starting at line 3404 in the current version 5.2.3).

If you need to make sure that multiple executions of msiexec were all successful you will need to code an intermediate layer. This can be as simple as a small stub that is executed in the [Run] entries and starts msiexec.exe with the correct parameters, waits for the process to finish, then writes the return code to a file.

Another way to check for success of such an installation step would be to add a custom procedure call for each [Run] entry by using the AfterInstall Parameter. In such a function you could for example check whether an OCX control has been successfully installed:

[Run]
Filename: "{tmp}\MyInstallation1.exe"; Parameters: "/foo"; AfterInstall: AfterMyInstallation1

[Code]
var
  MyInstallation1Success: boolean;

procedure AfterMyInstallation1;
var
  V: Variant;
begin
  try
    V := CreateOleObject('MyInstallation.InstalledOcxControl.1');
    MyInstallation1Success := True;
  except
    MyInstallation1Success := False;
  end;
end;

or whether the directories and registry entries for the dependency are all there.

Each [Run] entry is only executed when its optional Check parameter does return true. So depending on your needs you could either start all silent installations one after the other, and after the last has finished execute a script function to check that all dependencies were successfully installed; or you could write a check function for each dependency installation, which would then return false and thus skip all other installations after the first failed one.

Note however that all [Run] entries are executed after the steps for file copying, registry writing etc. are completed, so you are basically already finished with the installation. If you want to really execute all your installation steps only when all dependencies are correctly installed, then you would have to do that earlier in the process, when the installation can still be cancelled.

Edit: Check out the question "How do you make Inno Setup not look frozen while performing a long Exec?" where some information is given and a sample script is linked to about using the Exec() function for installing dependencies. So if you do not use [Run] entries there is a good chance to achieve what you want.

陌上芳菲 2024-07-21 06:46:53

您可以使用我的回答来解决类似问题,在[运行]部分中安全地运行命令,并提供适当的通知和错误时回滚。

上面的链接提供了完整的解决方案,但想法如下:

1)使用 InnoSetup 的 BeforeInstall 参数将错误消息写入临时文件 {tmp}\install.error 。

2) 使用 Windows 命令 shell“cmd.exe /s /c”运行所需的程序。 还可以使用带有“&&”的“del”命令的条件执行 - http:// /www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx?mfr=true。 因此,如果命令成功(退出代码 0),错误消息文件将被删除。 请注意“cmd.exe /s /c”中的特殊引号处理。

3) 使用 InnoSetup 的 AfterInstall 参数检查错误消息文件 {tmp}\install.error 是否存在,并通过适当的通知或确认(以及可选的日志文件显示)中止安装,并使用 Exec(ExpandConstant('{uninstallexe}') 执行回滚, ...

4)还需要执行一些额外的步骤,例如覆盖 InnoSetup 的 ShouldSkipPage(PageID: Integer) 函数以隐藏最终页面等。

You can use my answer to similar question to run commands safely in [Run] section with proper notification and rollback on error.

The link above provides complete solution, but idea is folowing:

1) Write error message to temporary file {tmp}\install.error using InnoSetup's BeforeInstall parameter.

2) Use Windows command shell "cmd.exe /s /c" to run desired program. Also use conditional execution of "del" command with "&&" - http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/ntcmds_shelloverview.mspx?mfr=true. So error message file would be deleted if command succeed (exit code 0). Please be aware of special quotes handling in "cmd.exe /s /c".

3) Check existence of error message file {tmp}\install.error using InnoSetup's AfterInstall parameter and abort install with proper notification or confirmation (and optional presenting of log file) and perform rollback using Exec(ExpandConstant('{uninstallexe}'), ...

4) There are some additional steps should be done like overriding InnoSetup's ShouldSkipPage(PageID: Integer) function to hide final page, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文