Debugowanie instalatora Inno Setup, który sam się odradza
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.iss
pliku i włączyła ją do mojego głównego skryptu.
Problem polega na tym, że po przekazaniu ShellExecute
połą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
Gdy debuger przejdzie przez ShellExecute
nowe 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 InitializeSetup
powrotu False
po ShellExecute
).
Martijn Laan (obecny opiekun Inno Setup) stwierdził, że Inno Setup nie jest przeznaczony do odradzania się. Właściwie własne Exec
API Inno Setup wyraźnie uniemożliwia ponowne odrodzenie instalatora. Ominięcie tego ograniczenia przy użyciu WinAPI ShellExecute
zamiast tego wprowadza problem opisany w pytaniu. Nie jest niespodzianką, że debuger nie radzi sobie z taką sytuacją.
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