forked from leapbtw/uxplay-windows
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.iss
More file actions
468 lines (417 loc) · 15.2 KB
/
Copy pathscript.iss
File metadata and controls
468 lines (417 loc) · 15.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{02621F03-7F92-4E33-AA17-017F79B31DCF}
AppName=uxplay-windows
AppVersion=1.72.1-3
;AppVerName=uxplay-windows 1.72.1-3
AppPublisher=leapbtw
AppPublisherURL=https://github.com/leapbtw/uxplay-windows
AppSupportURL=https://github.com/leapbtw/uxplay-windows
AppUpdatesURL=https://github.com/leapbtw/uxplay-windows
DefaultDirName={autopf}\uxplay-windows
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputBaseFilename=uxplay-windows
SetupIconFile=D:\a\uxplay-windows\uxplay-windows\icon.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "D:\a\uxplay-windows\uxplay-windows\dist\uxplay-windows\uxplay-windows.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "D:\a\uxplay-windows\uxplay-windows\dist\uxplay-windows\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\uxplay-windows"; Filename: "{app}\uxplay-windows.exe"
Name: "{autodesktop}\uxplay-windows"; Filename: "{app}\uxplay-windows.exe"; Tasks: desktopicon
[Run]
Filename: "{app}\uxplay-windows.exe"; Description: "{cm:LaunchProgram,uxplay-windows}"; Flags: shellexec postinstall skipifsilent
[Code]
// Constants
const
TH32CS_SNAPPROCESS = $00000002;
PROCESS_TERMINATE = $0001;
INVALID_HANDLE_VALUE = $FFFFFFFF;
// Type declarations
type
TProcessEntry32 = record
dwSize: DWORD;
cntUsage: DWORD;
th32ProcessID: DWORD;
th32DefaultHeapID: DWORD;
th32ModuleID: DWORD;
cntThreads: DWORD;
th32ParentProcessID: DWORD;
pcPriClassBase: Longint;
dwFlags: DWORD;
szExeFile: array[0..259] of AnsiChar;
end;
// Variables
var
BonjourDownloadPage: TDownloadWizardPage;
BonjourInstallNeeded: Boolean;
// Windows API declarations for process management
function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): THandle;
external 'CreateToolhelp32Snapshot@kernel32.dll stdcall';
function Process32First(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
external 'Process32First@kernel32.dll stdcall';
function Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;
external 'Process32Next@kernel32.dll stdcall';
function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';
function OpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle;
external 'OpenProcess@kernel32.dll stdcall';
function TerminateProcess(hProcess: THandle; uExitCode: UINT): BOOL;
external 'TerminateProcess@kernel32.dll stdcall';
function IsBonjourInstalled(): Boolean;
begin
Result := RegKeyExists(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Services\Bonjour Service');
end;
function IsProcessRunning(const ProcessName: String): Boolean;
var
hSnapshot: THandle;
ProcessEntry: TProcessEntry32;
Found: Boolean;
i: Integer;
ExeName: String;
begin
Result := False;
// Try-catch the entire function to prevent runtime errors
try
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hSnapshot = INVALID_HANDLE_VALUE then
begin
Log('Failed to create process snapshot');
Exit;
end;
try
ProcessEntry.dwSize := SizeOf(ProcessEntry);
Found := Process32First(hSnapshot, ProcessEntry);
while Found do
begin
// Safely convert szExeFile to String
ExeName := '';
try
for i := 0 to 259 do
begin
if ProcessEntry.szExeFile[i] = #0 then
Break;
ExeName := ExeName + ProcessEntry.szExeFile[i];
end;
except
// If string conversion fails, skip this entry
Found := Process32Next(hSnapshot, ProcessEntry);
Continue;
end;
if CompareText(ExeName, ProcessName) = 0 then
begin
Result := True;
Break;
end;
Found := Process32Next(hSnapshot, ProcessEntry);
end;
finally
CloseHandle(hSnapshot);
end;
except
// If any error occurs, just return False
Log('Exception in IsProcessRunning: ' + GetExceptionMessage);
Result := False;
end;
end;
function KillProcess(const ProcessName: String): Boolean;
var
hSnapshot: THandle;
ProcessEntry: TProcessEntry32;
Found: Boolean;
hProcess: THandle;
i: Integer;
ExeName: String;
begin
Result := False;
try
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hSnapshot = INVALID_HANDLE_VALUE then
begin
Log('Failed to create process snapshot for termination');
Exit;
end;
try
ProcessEntry.dwSize := SizeOf(ProcessEntry);
Found := Process32First(hSnapshot, ProcessEntry);
while Found do
begin
// Safely convert szExeFile to String
ExeName := '';
try
for i := 0 to 259 do
begin
if ProcessEntry.szExeFile[i] = #0 then
Break;
ExeName := ExeName + ProcessEntry.szExeFile[i];
end;
except
Found := Process32Next(hSnapshot, ProcessEntry);
Continue;
end;
if CompareText(ExeName, ProcessName) = 0 then
begin
hProcess := OpenProcess(PROCESS_TERMINATE, False, ProcessEntry.th32ProcessID);
if hProcess <> 0 then
try
Result := TerminateProcess(hProcess, 1);
finally
CloseHandle(hProcess);
end;
if Result then
Break;
end;
Found := Process32Next(hSnapshot, ProcessEntry);
end;
finally
CloseHandle(hSnapshot);
end;
except
Log('Exception in KillProcess: ' + GetExceptionMessage);
Result := False;
end;
end;
function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;
begin
if Progress = ProgressMax then
Log(Format('Successfully downloaded %s', [FileName]));
Result := True;
end;
procedure InitializeWizard;
begin
BonjourInstallNeeded := False;
// Check if Bonjour is installed
if not IsBonjourInstalled() then
begin
if MsgBox('uxplay-windows requires Bonjour Services to function properly, but it appears Bonjour is not installed on your system.' + #13#10#13#10 +
'Would you like us to automatically download and install Bonjour for you?' + #13#10#13#10 +
'Note: You will need to accept Bonjour''s license agreement during the installation process.',
mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
begin
BonjourInstallNeeded := True;
// Create download page
BonjourDownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), 'Downloading Bonjour...', @OnDownloadProgress);
BonjourDownloadPage.Clear;
BonjourDownloadPage.Add('https://download.info.apple.com/Mac_OS_X/061-8098.20100603.gthyu/BonjourPSSetup.exe', 'BonjourPSSetup.exe', '');
end
else
begin
MsgBox('Installation cannot continue without Bonjour Services.' + #13#10#13#10 +
'You can download Bonjour manually from:' + #13#10 +
'https://download.info.apple.com/Mac_OS_X/061-8098.20100603.gthyu/BonjourPSSetup.exe' + #13#10#13#10 +
'Please install Bonjour and run this installer again.',
mbError, MB_OK);
Abort;
end;
end;
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: Integer;
BonjourSetupPath: String;
ExtractPath: String;
BonjourMsiPath: String;
begin
Result := '';
if BonjourInstallNeeded then
begin
try
// Download Bonjour
BonjourDownloadPage.Show;
try
BonjourDownloadPage.Download;
BonjourSetupPath := ExpandConstant('{tmp}\BonjourPSSetup.exe');
except
Result := 'Failed to download Bonjour installer.';
Exit;
finally
BonjourDownloadPage.Hide;
end;
// Extract Bonjour setup
WizardForm.StatusLabel.Caption := 'Extracting Bonjour installer...';
WizardForm.ProgressGauge.Style := npbstMarquee;
ExtractPath := ExpandConstant('{tmp}\bonjour_extract');
CreateDir(ExtractPath);
if not Exec(BonjourSetupPath, '/extract "' + ExtractPath + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
Result := 'Failed to extract Bonjour installer.';
Exit;
end;
if ResultCode <> 0 then
begin
Result := 'Bonjour extraction failed with error code: ' + IntToStr(ResultCode);
Exit;
end;
// Find and install Bonjour64.msi
BonjourMsiPath := ExtractPath + '\Bonjour64.msi';
if not FileExists(BonjourMsiPath) then
begin
Result := 'Could not find Bonjour64.msi in extracted files.';
Exit;
end;
WizardForm.StatusLabel.Caption := 'Installing Bonjour Services...';
WizardForm.ProgressGauge.Style := npbstMarquee;
// Install Bonjour64.msi - NOT in background so user can accept license
if not Exec('msiexec.exe', '/i "' + BonjourMsiPath + '"', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
Result := 'Failed to start Bonjour installation.';
Exit;
end;
if ResultCode <> 0 then
begin
Result := 'Bonjour installation failed or was cancelled. Error code: ' + IntToStr(ResultCode) + #13#10#13#10 +
'uxplay-windows cannot be installed without Bonjour Services.';
Exit;
end;
// Verify Bonjour was installed successfully
if not IsBonjourInstalled() then
begin
Result := 'Bonjour installation completed but the service was not detected. Please restart your computer and try again.';
Exit;
end;
WizardForm.StatusLabel.Caption := 'Bonjour Services installed successfully.';
WizardForm.ProgressGauge.Style := npbstNormal;
except
Result := GetExceptionMessage;
end;
end;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// Skip the download page if we're not installing Bonjour
if Assigned(BonjourDownloadPage) and (PageID = BonjourDownloadPage.ID) and (not BonjourInstallNeeded) then
Result := True
else
Result := False;
end;
function InitializeSetup(): Boolean;
begin
Result := True;
end;
// Uninstall functions
function InitializeUninstall(): Boolean;
var
ProcessesKilled: Integer;
ProcessRunning: Boolean;
begin
Result := True;
ProcessesKilled := 0;
try
// Safely check and kill uxplay-windows.exe
try
ProcessRunning := IsProcessRunning('uxplay-windows.exe');
except
ProcessRunning := False;
Log('Could not check if uxplay-windows.exe is running');
end;
if ProcessRunning then
begin
try
if KillProcess('uxplay-windows.exe') then
begin
ProcessesKilled := ProcessesKilled + 1;
Log('Terminated uxplay-windows.exe process');
end
else
begin
// Don't fail uninstall, just warn user
Log('Could not terminate uxplay-windows.exe process automatically');
end;
except
Log('Exception while trying to kill uxplay-windows.exe');
end;
end;
// Safely check and kill uxplay.exe
try
ProcessRunning := IsProcessRunning('uxplay.exe');
except
ProcessRunning := False;
Log('Could not check if uxplay.exe is running');
end;
if ProcessRunning then
begin
try
if KillProcess('uxplay.exe') then
begin
ProcessesKilled := ProcessesKilled + 1;
Log('Terminated uxplay.exe process');
end
else
begin
Log('Could not terminate uxplay.exe process automatically');
end;
except
Log('Exception while trying to kill uxplay.exe');
end;
end;
if ProcessesKilled > 0 then
begin
try
MsgBox(Format('%d running process(es) were automatically terminated to proceed with uninstallation.', [ProcessesKilled]), mbInformation, MB_OK);
Sleep(1000);
except
// If even the message box fails, just continue
Log('Could not show process termination message');
end;
end;
except
Log('Exception in InitializeUninstall: ' + GetExceptionMessage);
// Always allow uninstall to continue even if process management fails
Result := True;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
ResultCode: Integer;
UninstallBonjourResult: Integer;
begin
if CurUninstallStep = usUninstall then
begin
// Ask user if they want to uninstall Bonjour as well
if IsBonjourInstalled() then
begin
UninstallBonjourResult := MsgBox('Would you also like to uninstall Bonjour Services?' + #13#10#13#10 +
'Note: Other applications may depend on Bonjour Services. ' +
'Only uninstall it if you are sure no other applications need it.',
mbConfirmation, MB_YESNO or MB_DEFBUTTON2);
if UninstallBonjourResult = IDYES then
begin
// Uninstall Bonjour using msiexec
if Exec('msiexec.exe', '/x {B91110FB-33B4-468B-90C2-4D5E8AE3FAE1} /quiet', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
if ResultCode = 0 then
begin
MsgBox('Bonjour Services has been successfully uninstalled.', mbInformation, MB_OK);
Log('Bonjour Services uninstalled successfully');
end
else
begin
MsgBox('Failed to uninstall Bonjour Services. Error code: ' + IntToStr(ResultCode) + #13#10#13#10 +
'You can uninstall it manually from Control Panel > Programs and Features.',
mbError, MB_OK);
Log('Bonjour Services uninstall failed with error code: ' + IntToStr(ResultCode));
end;
end
else
begin
MsgBox('Could not start Bonjour Services uninstallation.' + #13#10#13#10 +
'You can uninstall it manually from Control Panel > Programs and Features.',
mbError, MB_OK);
Log('Failed to execute Bonjour Services uninstaller');
end;
end;
end;
end;
end;