问题描述
从 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