Debugowanie instalatora Inno Setup, który sam się odradza

Dec 21 2020

Jak widać z tego pytania uruchamiamy nową instancję Inno Setup:

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

gdzie

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

Cały kod z tym odpowiedź na pytanie I przeniesione do VCL_Styles.isspliku i włączyła ją do mojego głównego skryptu.

Problem polega na tym, że po przekazaniu ShellExecutepołączenia i zakończeniu przez debugger, jedna instancja Inno Setup nadal działa (więc muszę zakończyć proces za pomocą Menedżera zadań Windows) i otrzymuję następujące komunikaty w Debug Output:

***Proces zakończenia

*** Usuwanie pozostałego katalogu tymczasowego: C:\Users\JCONST~1\AppData\Local\Temp\is-PV9OS.tmp

*** Instalator nadal działa; nie mogę uzyskać kodu wyjścia

zamiast kodu wyjścia 6, który zgodnie z dokumentacją jest zwracany, gdy:

Proces instalacji został wymuszany przez debuger (w środowisku IDE kompilatora użyto opcji Run | Terminate).

Nie jestem pewien, która instancja Inno Setup jest nadal uruchomiona i jak mogę ją zatrzymać?

Oto zawartość VCL.Styles, którą włączam do mojego głównego skryptu, więc otrzymuję wyżej wymieniony błąd:

[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;

Odpowiedzi

1 MartinPrikryl Dec 28 2020 at 14:51

Gdy debuger przejdzie przez ShellExecutenowe wystąpienie procesu instalatora, wydaje się, że debuger IDE wybiera ten proces i ponownie uruchamia debugowanie. Zakładam, że nie jest to zamierzone zachowanie, a przynajmniej nie jest to dobrze przetestowane. Funkcja Terminate prawdopodobnie próbuje wtedy zamknąć/komunikować się ze starym procesem (który w międzyczasie sam się zakończył – z powodu InitializeSetuppowrotu Falsepo ShellExecute).

Martijn Laan (obecny opiekun Inno Setup) stwierdził, że Inno Setup nie jest przeznaczony do odradzania się. Właściwie własne ExecAPI Inno Setup wyraźnie uniemożliwia ponowne odrodzenie instalatora. Ominięcie tego ograniczenia przy użyciu WinAPI ShellExecutezamiast tego wprowadza problem opisany w pytaniu. Nie jest niespodzianką, że debuger nie radzi sobie z taką sytuacją.

JConstantine Dec 21 2020 at 21:46

Wygląda na to, że błąd IDE Inno Setup mógł spowodować ten problem.

Oto link do raportu:

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