@@ -29,7 +29,10 @@ DefaultDirName="{autopf64}\UniGetUI"
2929DisableProgramGroupPage = yes
3030DisableDirPage = no
3131DirExistsWarning = no
32- CloseApplications = no
32+ ; Force-close any process holding files we overwrite (backstop for the kill in PrepareToInstall).
33+ CloseApplications = force
34+ CloseApplicationsFilter = *.exe,*.dll
35+ RestartApplications = no
3336; Default to per-user install mode and let the dialog opt into all-users installs when needed.
3437PrivilegesRequired = lowest
3538PrivilegesRequiredOverridesAllowed= dialog
@@ -97,19 +100,70 @@ begin
97100 WizardForm.Bevel1.Visible := True;
98101end ;
99102
100- procedure TaskKill (FileName: String);
103+ // Kills all instances of an image and loops until none remain (taskkill returns 0 while killing, 128 when none left).
104+ procedure TaskKillWait (FileName: String);
101105var
102- ResultCode: Integer;
106+ ResultCode, Attempts : Integer;
103107begin
104- Exec(' taskkill.exe' , ' /f /im ' + ' "' + FileName + ' "' , ' ' , SW_HIDE,
105- ewWaitUntilTerminated, ResultCode);
108+ Attempts := 0 ;
109+ repeat
110+ if not Exec(' taskkill.exe' , ' /f /im "' + FileName + ' "' , ' ' , SW_HIDE,
111+ ewWaitUntilTerminated, ResultCode) then
112+ Break;
113+ if ResultCode <> 0 then
114+ Break;
115+ Sleep(500 );
116+ Attempts := Attempts + 1 ;
117+ until Attempts >= 10 ;
106118end ;
107119
108120procedure KillRunningApps ;
109121begin
110- TaskKill(' WingetUI.exe' );
111- TaskKill(' UniGetUI.exe' );
112- TaskKill(' UniGetUI.Avalonia.exe' );
122+ TaskKillWait(' WingetUI.exe' );
123+ TaskKillWait(' UniGetUI.exe' );
124+ TaskKillWait(' UniGetUI.Avalonia.exe' );
125+ // Elevator (gsudo cache) and pinget live in {app} and lock their own files.
126+ TaskKillWait(' UniGetUI Elevator.exe' );
127+ TaskKillWait(' pinget.exe' );
128+ Sleep(1000 ); // let the OS release file handles before copying
129+
130+ end ;
131+
132+ function GetCurrentProcessId : Cardinal; external ' GetCurrentProcessId@kernel32.dll stdcall' ;
133+
134+ function UpdateMarkerPath (): String;
135+ begin
136+ Result := ExpandConstant(' {app}\.unigetui-update-in-progress' );
137+ end ;
138+
139+ // Marker holds our PID; the app blocks only while this installer runs. Name MUST match UpdateInProgressGuard.MarkerFileName.
140+ procedure WriteUpdateMarker ;
141+ var
142+ Pid: Int64;
143+ begin
144+ ForceDirectories(ExpandConstant(' {app}' ));
145+ Pid := GetCurrentProcessId;
146+ SaveStringToFile(UpdateMarkerPath(), IntToStr(Pid), False);
147+ end ;
148+
149+ procedure RemoveUpdateMarker ;
150+ begin
151+ DeleteFile(UpdateMarkerPath());
152+ end ;
153+
154+ // Runs before any file is copied: shut everything down, then mark the copy window.
155+ function PrepareToInstall (var NeedsRestart: Boolean): String;
156+ begin
157+ KillRunningApps;
158+ WriteUpdateMarker;
159+ Result := ' ' ;
160+ end ;
161+
162+ // Clear the marker once the copy is done, before the post-install launch.
163+ procedure CurStepChanged (CurStep: TSetupStep);
164+ begin
165+ if CurStep = ssPostInstall then
166+ RemoveUpdateMarker;
113167end ;
114168
115169function CmdLineParamExists (const Value : string): Boolean;
@@ -132,6 +186,8 @@ procedure ExitProcess(exitCode:integer);
132186
133187procedure DeinitializeSetup ();
134188begin
189+ RemoveUpdateMarker; // also clear on abort, before ssPostInstall
190+
135191 if (CustomExitCode <> 0 ) then
136192 begin
137193 DelTree(ExpandConstant(' {tmp}' ), True, True, True);
@@ -215,8 +271,8 @@ Root: HKA; Subkey: "Software\Classes\UniGetUI.PackageBundle\shell\open\command";
215271Source : " {srcexe} " ; DestDir : " {app} " ; DestName : " UniGetUI.Installer.exe" ; Flags : external ignoreversion ; Tasks: regularinstall; Check : not CmdLineParamExists(' /NoDeployInstaller' );
216272; Deploy integrity tree
217273Source : " unigetui_bin\IntegrityTree.json" ; DestDir : " {app} " ; Flags : createallsubdirs ignoreversion recursesubdirs ;
218- ; Deploy executable files
219- Source : " unigetui_bin\{#MyAppExeName}" ; DestDir : " {app} " ; Flags : ignoreversion ; BeforeInstall : KillRunningApps;
274+ ; Deploy executable files (running instances already killed in PrepareToInstall).
275+ Source : " unigetui_bin\{#MyAppExeName}" ; DestDir : " {app} " ; Flags : ignoreversion ;
220276Source : " unigetui_bin\*" ; DestDir : " {app} " ; Flags : createallsubdirs ignoreversion recursesubdirs ;
221277; Make installation portable (if required)
222278Source : " InstallerExtras\ForceUniGetUIPortable" ; DestDir : " {app} " ; Tasks: portableinstall
0 commit comments