66#define MyServiceName " Cleanuparr"
77
88[Setup]
9- ; NOTE: The value of AppId uniquely identifies this application.
10- ; Do not use the same AppId value in installers for other applications.
119AppId = {{E8B2C9D4-6F87-4E42-B5C3-29E121D4BDFF}
1210AppName = {#MyAppName }
1311AppVersion = {#MyAppVersion}
@@ -43,10 +41,8 @@ Name: "installservice"; Description: "Install as Windows Service (Recommended)";
4341
4442[Files]
4543Source : " dist\*" ; DestDir : " {app} " ; Flags : ignoreversion recursesubdirs createallsubdirs
46- ; Application icon
4744Source : " Logo\favicon.ico" ; DestDir : " {app} " ; Flags : ignoreversion
48- ; Create sample configuration
49- Source : " config\cleanuparr.json" ; DestDir : " {app} \config" ; Flags : ignoreversion ; AfterInstall : CreateConfigDirs
45+ ; Note: Application will create its own configuration files
5046
5147[Dirs]
5248Name : " {app} \config" ; Permissions: everyone-full
@@ -57,70 +53,161 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
5753Name : " {commondesktop}\{#MyAppName}" ; Filename : " {app} \{#MyAppExeName}" ; IconFilename: " {app} \favicon.ico" ; Tasks: desktopicon
5854
5955[Run]
60- ; Stop any existing service first
61- Filename : " {sys} \sc.exe" ; Parameters : " stop " " {#MyServiceName}" " " ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
62- ; Wait for service to stop
63- Filename : " {sys} \timeout.exe " ; Parameters : " /t 3 " ; Flags : runhidden ; Check : ServiceExists( ' {#MyServiceName} ' )
64- ; Remove existing service
65- Filename : " {sys} \sc.exe" ; Parameters : " delete " " {#MyServiceName}" " " ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
66- ; Install as service
67- Filename : " {sys} \sc.exe " ; Parameters : " create " " {#MyServiceName} " " binPath= " " \ " " {app} \{#MyAppExeName}\ " " " " DisplayName= " " {#MyAppName} " " start= auto " ; Tasks: installservice; Flags : runhidden
68- ; Configure service description
69- Filename : " {sys} \sc.exe" ; Parameters : " description " " {#MyServiceName}" " " " Cleanuparr download management service " " " ; Tasks: installservice; Flags : runhidden
70- ; Start the service
71- Filename : " {sys} \sc.exe " ; Parameters : " start " " {#MyServiceName} " " " ; Tasks: installservice; Flags : runhidden
72- ; Open web interface
73- Filename : " http://localhost:11011 " ; Description : " Open Cleanuparr Web Interface " ; Flags : postinstall shellexec nowait
56+ ; For fresh installs only - create and start service
57+ Filename : " {sys} \sc.exe" ; Parameters : " create " " {#MyServiceName}" " binPath= " " \ " " {app} \{#MyAppExeName}\ " " " " DisplayName= " " {#MyAppName} " " start= auto " ; Tasks: installservice; Flags : runhidden ; Check : not ServiceExists(' {#MyServiceName}' )
58+ Filename : " {sys} \sc.exe " ; Parameters : " description " " {#MyServiceName} " " " " Cleanuparr download management service" " " ; Tasks: installservice; Flags : runhidden ; Check : not ServiceExists( ' {#MyServiceName} ' )
59+
60+ ; For updates - stop service if running, wait for complete shutdown, then restart
61+ Filename : " {sys} \sc.exe" ; Parameters : " stop " " {#MyServiceName}" " " ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' ) and IsServiceRunning( ' {#MyServiceName} ' ) and IsTaskSelected( ' installservice ' )
62+ Filename : " {sys} \sc.exe " ; Parameters : " start " " {#MyServiceName} " " " ; Tasks: installservice; Flags : runhidden ; Check : ServiceExists( ' {#MyServiceName} ' ) and WasServiceExisting
63+
64+ ; For fresh installs - start the newly created service
65+ Filename : " {sys} \sc.exe" ; Parameters : " start " " {#MyServiceName}" " " ; Tasks: installservice; Flags : runhidden ; Check : not WasServiceExisting
66+
67+ ; Open web interface (only if service is selected)
68+ Filename : " http://localhost:11011 " ; Description : " Open Cleanuparr Web Interface " ; Flags : postinstall shellexec nowait ; Check : IsTaskSelected( ' installservice ' )
69+
7470; Run directly (if not installed as service)
7571Filename : " {app} \{#MyAppExeName}" ; Description : " Run {#MyAppName} Application" ; Flags : nowait postinstall skipifsilent ; Check : not IsTaskSelected(' installservice' )
7672
7773[UninstallRun]
78- ; Stop the service first
7974Filename : " {sys} \sc.exe" ; Parameters : " stop " " {#MyServiceName}" " " ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
80- ; Wait for service to stop
81- Filename : " {sys} \timeout.exe" ; Parameters : " /t 3" ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
82- ; Remove the service
75+ Filename : " {sys} \timeout.exe" ; Parameters : " /t 5" ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
8376Filename : " {sys} \sc.exe" ; Parameters : " delete " " {#MyServiceName}" " " ; Flags : runhidden ; Check : ServiceExists(' {#MyServiceName}' )
8477
8578[Code]
79+ var
80+ WasServiceExisting: Boolean;
81+
8682procedure CreateConfigDirs ;
8783begin
88- // Create necessary directories with proper permissions
84+ // Create config directory - application will create its own config files
8985 ForceDirectories(ExpandConstant(' {app}\config' ));
9086end ;
9187
9288function ServiceExists (ServiceName: string): Boolean;
9389var
9490 ResultCode: Integer;
9591begin
96- // Check if service exists by trying to query it
9792 Result := Exec(ExpandConstant(' {sys}\sc.exe' ), ' query "' + ServiceName + ' "' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 );
9893end ;
9994
100- // Check for running processes before install
95+ function IsServiceRunning (ServiceName: string): Boolean;
96+ var
97+ ResultCode: Integer;
98+ Output: AnsiString;
99+ OutputFile: string;
100+ begin
101+ Result := False;
102+ OutputFile := ExpandConstant(' {tmp}\service_status.txt' );
103+
104+ // Query service status and capture output
105+ if Exec(ExpandConstant(' {sys}\sc.exe' ), ' query "' + ServiceName + ' "' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 ) then
106+ begin
107+ // Use PowerShell to get service status more reliably
108+ if Exec(ExpandConstant(' {sys}\WindowsPowerShell\v1.0\powershell.exe' ),
109+ ' -Command "& {(Get-Service -Name '' ' + ServiceName + ' '' -ErrorAction SilentlyContinue).Status}"' ,
110+ ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
111+ begin
112+ // If we can't determine status precisely, assume it might be running to be safe
113+ Result := True;
114+ end ;
115+ end ;
116+ end ;
117+
118+ function WaitForServiceStop (ServiceName: string): Boolean;
119+ var
120+ Counter: Integer;
121+ ResultCode: Integer;
122+ StatusOutput: AnsiString;
123+ TempFile: string;
124+ begin
125+ Result := True;
126+ Counter := 0 ;
127+ TempFile := ExpandConstant(' {tmp}\service_check.txt' );
128+
129+ // Wait up to 30 seconds for service to stop
130+ while Counter < 30 do
131+ begin
132+ // Check service status using PowerShell for more reliable output
133+ if Exec(ExpandConstant(' {sys}\WindowsPowerShell\v1.0\powershell.exe' ),
134+ ' -Command "& {try { $s = Get-Service -Name '' ' + ServiceName + ' '' -ErrorAction Stop; $s.Status } catch { '' NotFound'' }}" > "' + TempFile + ' "' ,
135+ ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
136+ begin
137+ if LoadStringFromFile(TempFile, StatusOutput) then
138+ begin
139+ // If service is stopped or not found, we're good
140+ if (Pos(' Stopped' , StatusOutput) > 0 ) or (Pos(' NotFound' , StatusOutput) > 0 ) then
141+ begin
142+ DeleteFile(TempFile);
143+ Exit;
144+ end ;
145+ end ;
146+ end ;
147+
148+ Sleep(1000 );
149+ Counter := Counter + 1 ;
150+ end ;
151+
152+ // Cleanup temp file
153+ DeleteFile(TempFile);
154+
155+ // If we get here, service didn't stop in time
156+ if Counter >= 30 then
157+ begin
158+ MsgBox(' Warning: Service took longer than expected to stop. Installation will continue but the service may need to be restarted manually.' ,
159+ mbInformation, MB_OK);
160+ Result := False;
161+ end ;
162+ end ;
163+
101164function InitializeSetup (): Boolean;
102165var
103166 ResultCode: Integer;
104167begin
105- // Try to stop the service if it's running
106- if ServiceExists(' {#MyServiceName}' ) then
168+ // Remember if service existed before installation
169+ WasServiceExisting := ServiceExists(' {#MyServiceName}' );
170+
171+ // Only stop service if it exists and is running
172+ if WasServiceExisting and IsServiceRunning(' {#MyServiceName}' ) then
107173 begin
108- Exec(ExpandConstant(' {sys}\sc.exe' ), ' stop "{#MyServiceName}"' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode);
109- Sleep(3000 );
174+ if MsgBox(' Cleanuparr service is currently running and needs to be stopped for the installation. Continue?' ,
175+ mbConfirmation, MB_YESNO) = IDYES then
176+ begin
177+ Exec(ExpandConstant(' {sys}\sc.exe' ), ' stop "{#MyServiceName}"' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode);
178+ if not WaitForServiceStop(' {#MyServiceName}' ) then
179+ begin
180+ // Service didn't stop properly, but continue anyway
181+ Log(' Warning: Service did not stop cleanly, continuing with installation' );
182+ end ;
183+ end
184+ else
185+ begin
186+ Result := False;
187+ Exit;
188+ end ;
110189 end ;
190+
111191 Result := True;
112192end ;
113193
114- // Handle cleanup before uninstall
115194function InitializeUninstall (): Boolean;
116195var
117196 ResultCode: Integer;
118197begin
119- // Stop the service before uninstalling
120198 if ServiceExists(' {#MyServiceName}' ) then
121199 begin
122- Exec(ExpandConstant(' {sys}\sc.exe' ), ' stop "{#MyServiceName}"' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode);
123- Sleep(3000 );
200+ if MsgBox(' Cleanuparr service will be stopped and removed. Continue with uninstallation?' ,
201+ mbConfirmation, MB_YESNO) = IDYES then
202+ begin
203+ Exec(ExpandConstant(' {sys}\sc.exe' ), ' stop "{#MyServiceName}"' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode);
204+ WaitForServiceStop(' {#MyServiceName}' );
205+ end
206+ else
207+ begin
208+ Result := False;
209+ Exit;
210+ end ;
124211 end ;
125212 Result := True;
126- end ;
213+ end ;
0 commit comments