自分自身をリスポーンするInnoSetupインストーラーのデバッグ

Dec 21 2020

この質問からわかるように、InnoSetupの新しいインスタンスを開始します。

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

どこ

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
      lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
      external '[email protected] stdcall';

この質問の回答のすべてのコードをVCL_Styles.issファイルに移動し、メインスクリプトに含めました。

問題は、ShellExecute呼び出しを通過してデバッガーで終了した後、Inno Setupの1つのインスタンスが実行され続け(したがって、Windowsタスクマネージャーを使用してプロセスを強制終了する必要があります)、次のメッセージが表示されることDebug Outputです。

***終了プロセス

***残った一時ディレクトリの削除:C:\ Users \ JCONST〜1 \ AppData \ Local \ Temp \ is-PV9OS.tmp

***セットアップはまだ実行中です。終了コードを取得できません

ドキュメントによると、次の場合に返される終了コード6の代わりに:

セットアッププロセスはデバッガーによって強制的に終了されました(コンパイラIDEでは[実行] | [終了]が使用されました)。

Inno Setupのどのインスタンスがまだ実行されているのかわかりません。どうすれば停止できますか?

VCL.Stylesメインスクリプトに含める内容は次のとおりです。前述のエラーが発生します。

[Setup]
ShowLanguageDialog=no

[Code]
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
  external '[email protected] stdcall';

<event('InitializeSetup')>
function MyInitializeSetup2: Boolean;
var
  Instance: THandle;
  I: Integer;
  S, Params, 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, '', ExpandConstant('{srcexe}'), Params, '', 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;

回答

1 MartinPrikryl Dec 28 2020 at 14:51

デバッガーがステップオーバーしShellExecute、インストーラープロセスの新しいインスタンスが開始されると、IDEデバッガーはそのプロセスを選択し、デバッグを再開するようです。これは意図された動作ではないか、少なくとも十分にテストされた動作ではないと思います。次に、Terminate関数は、おそらく古いプロセスを閉じたり、古いプロセスと通信しようとします(その間に、がInitializeSetup戻ってきFalseたために、自動的に終了しましたShellExecute)。

Martijn Laan(Inno Setupの現在のメンテナー)は、InnoSetupはそれ自体をリスポーンするようには設計されていないと述べました。実際、Inno Setup独自のExecAPIは、インストーラーの再生成を明示的に防止します。ShellExecute代わりに、WinAPIを使用してこの制限をバイパスすると、質問で説明されている問題が発生します。デバッガーがこの状況を処理できないのは当然のことです。

JConstantine Dec 21 2020 at 21:46

InnoSetupのIDEバグがその問題を引き起こした可能性があるようです。

レポートのリンクは次のとおりです。

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