调试自身重生的 Inno Setup 安装程序

问题描述

this 问题可以看出,我们启动了一个 Inno Setup 的新实例:

Instance := ShellExecute(0,'',ExpandConstant('{srcexe}'),Params,SW_SHOW);

哪里

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
      lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
      external 'ShellExecuteW@shell32.dll stdcall';

我将 this 问题答案中的所有代码移至 VCL_Styles.iss 文件并将其包含在我的主脚本中。

问题是,在我通过 ShellExecute 调用并由调试器终止之后,Inno Setup 的一个实例继续运行(所以我必须使用 Windows 任务管理器终止进程),我得到以下信息Debug Output 中的消息:

*** 终止进程

*** 删除剩余的临时目录:C:\Users\JCONST~1\AppData\Local\Temp\is-PV9OS.tmp

*** 安装程序仍在运行;无法获取退出代码

而不是根据 documentation 返回的退出代码 6:

安装进程被调试器强行终止 (Run | 编译器 IDE 中使用了 Terminate。

我不确定 Inno Setup 的哪个实例仍在运行,我该如何停止它?

这是我包含在主脚本中的 VCL.Styles内容,因此我收到了上述错误

[Setup]
ShowLanguageDialog=no

[Code]
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
  external 'ShellExecuteW@shell32.dll stdcall';

<event('InitializeSetup')>
function MyInitializeSetup2: Boolean;
var
  Instance: THandle;
  I: Integer;
  S,Language: String;
begin
  Result := True;

  for I := 1 to ParamCount do
    begin
      S := ParamStr(I);
      if CompareText(copy(S,1,5),'/SL5=') <> 0 then
      begin
        Params := Params + AddQuotes(S) + ' ';
      end;
    end;

  Params := Params + '/LANG=en';
  Language := ExpandConstant('{param:LANG}');
  if Language = '' then
    begin
      Instance := ShellExecute(0,SW_SHOW);
      if Instance <= 32 then
        begin
          S := 'Running installer with the selected language Failed. Code: %d';
          MsgBox(Format(S,[Instance]),mbError,MB_OK);
        end;
      Result := False;
      Exit;
    end;
end;

解决方法

当调试器跳过 ShellExecute 并启动安装程序进程的新实例时,IDE 调试器似乎会选择该进程并重新启动调试。我认为这不是预期的行为,或者至少不是经过充分测试的行为。 Terminate 函数然后可能会尝试关闭/与旧进程通信(它同时已自行终止 - 由于其 InitializeSetup 在 {{1} 之后返回 False }}).

Martijn Laan(Inno Setup 的当前维护者)表示 Inno Setup 并不是为了重生而设计的。实际上 Inno Setup 自己的 ShellExecute API 明确防止重新生成安装程序。使用 WinAPI Exec 绕过此限制会引入问题中描述的问题。调试器无法处理这种情况也就不足为奇了。

,

看起来可能是 Inno Setup 的 IDE 错误导致了该问题。

这是报告链接:

https://groups.google.com/g/innosetup/c/pDSbgD8nbxI/m/0lvTsslOAwAJ