Debugging Inno Setup installer that respawns itself

允我心安 提交于 2021-02-07 10:33:16

问题


As it can be seen from this question we start a new instance of Inno Setup:

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

where

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

All the code from this question's answer I moved to the VCL_Styles.iss file and included it into my main script.

The problem is that after I've passed the ShellExecute call and terminate by the debugger afterwards one instance of Inno Setup keeps running (so I have to kill the process using Windows Task Manager) and I get the following messages in the Debug Output:

*** Terminating process

*** Removing left-over temporary directory: C:\Users\JCONST~1\AppData\Local\Temp\is-PV9OS.tmp

*** Setup is still running; can't get exit code

instead of exit code 6 which according to the documentation is returned when:

The Setup process was forcefully terminated by the debugger (Run | Terminate was used in the Compiler IDE).

I'm not sure which instance of Inno Setup is still running and how can I stop it?

Here's the contents of the VCL.Styles that I include into my main script so I get the aforementioned error:

[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, 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:


When the debugger steps over the ShellExecute and the new instance of the installer process is started, the IDE debugger seems to pick that process and restarts the debugging. I assume this is not intended behaviour, or at least not a well-tested one. The Terminate function then probably tries to close/communicate with to the old process (which has terminated on its own meanwhile – due to its InitializeSetup returning False after the ShellExecute).

Martijn Laan (the current maintainer of Inno Setup) stated that Inno Setup is not designed to respawn itself. Actually Inno Setup own Exec API explicitly prevents respawning the installer. Bypassing this restriction by using WinAPI ShellExecute instead introduces the problem described in the question. It's not a surprise that the debugger cannot handle this situation.




回答2:


Looks like an Inno Setup's IDE bug may have caused that problem.

Here's the report link:

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



来源:https://stackoverflow.com/questions/65389216/debugging-inno-setup-installer-that-respawns-itself

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!