-
Notifications
You must be signed in to change notification settings - Fork 255
Expand file tree
/
Copy pathinstaller.iss
More file actions
350 lines (308 loc) · 12.1 KB
/
Copy pathinstaller.iss
File metadata and controls
350 lines (308 loc) · 12.1 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
; OpenClaw Companion Inno Setup Script (WinUI version)
; Pass /DDevBuild=1 to produce a side-by-side dev installer.
#ifdef DevBuild
#define MyAppName "OpenClaw Companion (Dev)"
#define MyAppAumid "OpenClaw.Companion.Dev"
#define MyAppId "{{M0LTB0T-TRAY-4PP1-DEV}"
#define MyInstallDir "OpenClawTray-Dev"
#define MyMutex "OpenClawTray-Dev"
#define MyAutoStartName "OpenClawTray-Dev"
#define MyStartupTaskName "OpenClaw Companion (Dev)"
#define MyDistroName "OpenClawGateway-Dev"
#define MyProtocol "openclaw-dev"
#define MyOutputSuffix "-Dev"
#else
#define MyAppName "OpenClaw Companion"
#define MyAppAumid "OpenClaw.Companion"
#define MyAppId "{{M0LTB0T-TRAY-4PP1-D3N7}"
#define MyInstallDir "OpenClawTray"
#define MyMutex "OpenClawTray"
#define MyAutoStartName "OpenClawTray"
#define MyStartupTaskName "OpenClaw Companion"
#define MyDistroName "OpenClawGateway"
#define MyProtocol "openclaw"
#define MyOutputSuffix ""
#endif
#define MyAppPublisher "OpenClaw Foundation"
#define MyAppURL "https://github.com/openclaw/openclaw-windows-node"
#define MyAppExeName "OpenClaw.Tray.WinUI.exe"
; MyAppArch should be passed via /DMyAppArch=x64 or /DMyAppArch=arm64
#ifndef MyAppArch
#define MyAppArch "x64"
#endif
#ifndef MyCompression
#define MyCompression "lzma"
#endif
#ifndef MySolidCompression
#define MySolidCompression "yes"
#endif
[Setup]
; Inno requires "{{" to emit a literal opening brace in AppId.
; Do not add a second closing brace here; that creates a malformed uninstall registry key.
AppId={#MyAppId}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL=https://github.com/openclaw/openclaw-windows-node/issues
AppUpdatesURL=https://github.com/openclaw/openclaw-windows-node/releases
DefaultDirName={localappdata}\{#MyInstallDir}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputBaseFilename=OpenClawCompanion{#MyOutputSuffix}-Setup-{#MyAppArch}
Compression={#MyCompression}
SolidCompression={#MySolidCompression}
WizardStyle=modern
PrivilegesRequired=lowest
SetupIconFile=src\OpenClaw.Tray.WinUI\Assets\openclaw.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
; Round 2 (Scott #5): block install/uninstall while the tray is running.
; Mutex name matches AppIdentity.MutexBaseName for this build variant.
; Tray and Inno run in the same user session, so no Global\ prefix is needed.
AppMutex={#MyMutex}
#if MyAppArch == "arm64"
ArchitecturesInstallIn64BitMode=arm64
ArchitecturesAllowed=arm64
#else
ArchitecturesInstallIn64BitMode=x64
ArchitecturesAllowed=x64
#endif
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
; publish folder should be passed via /Dpublish=publish-x64 or /Dpublish=publish-arm64
#ifndef publish
#define publish "publish"
#endif
#if !FileExists(publish + "\OpenClaw.Tray.WinUI.exe")
#error Tray payload missing. Publish OpenClaw.Tray.WinUI before compiling the installer.
#endif
#if FileExists(publish + "\SetupEngine\OpenClaw.SetupEngine.UI.exe")
#error SetupEngine.UI.exe should not be shipped. Setup UI is hosted by OpenClaw.Tray.WinUI.exe.
#endif
; vcRedist should point at the architecture-matching Visual C++ Runtime
; redistributable in CI release builds.
#ifndef vcRedist
#define vcRedist ""
#endif
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "startupicon"; Description: "Start {#MyAppName} when Windows starts"; GroupDescription: "Startup:"; Flags: unchecked
[Files]
; WinUI Tray app - include all files (WinUI needs DLLs, not single-file)
Source: "{#publish}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; WSL gateway uninstall helper copied to {tmp} by [Code] during uninstall.
Source: "scripts\Uninstall-LocalGateway.ps1"; DestDir: "{app}"; Flags: ignoreversion
#if vcRedist != ""
Source: "{#vcRedist}"; DestDir: "{tmp}"; DestName: "vc_redist.exe"; Flags: deleteafterinstall; AfterInstall: InstallVCRuntime
#endif
[Registry]
Root: HKCU; Subkey: "Software\Classes\{#MyProtocol}"; ValueType: string; ValueName: ""; ValueData: "URL:OpenClaw Protocol"; Flags: uninsdeletekey
Root: HKCU; Subkey: "Software\Classes\{#MyProtocol}"; ValueType: string; ValueName: "URL Protocol"; ValueData: ""
Root: HKCU; Subkey: "Software\Classes\{#MyProtocol}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"",0"
Root: HKCU; Subkey: "Software\Classes\{#MyProtocol}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; AppUserModelID: "{#MyAppAumid}"
Name: "{group}\OpenClaw Gateway Setup"; Filename: "{app}\{#MyAppExeName}"; Parameters: "{#MyProtocol}://setup"; IconFilename: "{app}\{#MyAppExeName}"; AppUserModelID: "{#MyAppAumid}"
Name: "{group}\OpenClaw Companion Settings"; Filename: "{app}\{#MyAppExeName}"; Parameters: "{#MyProtocol}://commandcenter"; IconFilename: "{app}\{#MyAppExeName}"; AppUserModelID: "{#MyAppAumid}"
Name: "{group}\OpenClaw Chat"; Filename: "{app}\{#MyAppExeName}"; Parameters: "{#MyProtocol}://chat"; IconFilename: "{app}\{#MyAppExeName}"; AppUserModelID: "{#MyAppAumid}"
Name: "{group}\Check for Updates"; Filename: "{app}\{#MyAppExeName}"; Parameters: "{#MyProtocol}://check-updates"; IconFilename: "{app}\{#MyAppExeName}"; AppUserModelID: "{#MyAppAumid}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon; AppUserModelID: "{#MyAppAumid}"
Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startupicon; AppUserModelID: "{#MyAppAumid}"
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent; Check: ShouldLaunchTray
[Code]
var
VCRuntimeInstallSucceeded: Boolean;
LocalGatewayCleanupChoiceInitialized: Boolean;
LocalGatewayCleanupRequested: Boolean;
LocalGatewayCleanupSucceeded: Boolean;
#if vcRedist != ""
procedure InstallVCRuntime;
var
ResultCode: Integer;
Started: Boolean;
begin
VCRuntimeInstallSucceeded := False;
Log('Running bundled Visual C++ Runtime redistributable.');
Started :=
Exec(
ExpandConstant('{tmp}\vc_redist.exe'),
'/install /quiet /norestart',
'',
SW_HIDE,
ewWaitUntilTerminated,
ResultCode);
if not Started then
begin
Log('Failed to start Visual C++ Runtime redistributable. System error: ' + IntToStr(ResultCode) + '.');
Exit;
end;
VCRuntimeInstallSucceeded := (ResultCode = 0) or (ResultCode = 3010) or (ResultCode = 1641);
if VCRuntimeInstallSucceeded then
Log('Visual C++ Runtime redistributable exited with success code ' + IntToStr(ResultCode) + '.')
else
Log('Visual C++ Runtime redistributable failed with exit code ' + IntToStr(ResultCode) + '.');
end;
#endif
function ShouldLaunchTray: Boolean;
begin
#if vcRedist != ""
Result := VCRuntimeInstallSucceeded;
if not Result then
Log('Skipping post-install tray launch because Visual C++ Runtime installation did not succeed.');
#else
Result := True;
#endif
end;
procedure EnsureLocalGatewayCleanupChoice;
begin
if LocalGatewayCleanupChoiceInitialized then
Exit;
LocalGatewayCleanupChoiceInitialized := True;
if UninstallSilent() then
begin
LocalGatewayCleanupRequested := True;
Log('Silent uninstall: local gateway cleanup will run automatically.');
end
else
begin
LocalGatewayCleanupRequested :=
MsgBox(
'Do you also want to remove the OpenClaw local WSL gateway?' + #13#10#13#10 +
'Choose Yes to unregister the {#MyDistroName} WSL distro and remove generated local gateway state.' + #13#10 +
'Choose No to leave the local gateway and generated local state on this computer.',
mbConfirmation,
MB_YESNO) = IDYES;
if LocalGatewayCleanupRequested then
Log('User chose to remove the local WSL gateway.')
else
Log('User chose to preserve the local WSL gateway and generated state.');
end;
end;
function RunLocalGatewayCleanupOnce(var ResultCode: Integer): Boolean;
var
SourceScriptPath: string;
TempScriptPath: string;
Params: string;
begin
SourceScriptPath := ExpandConstant('{app}\Uninstall-LocalGateway.ps1');
TempScriptPath := ExpandConstant('{tmp}\Uninstall-LocalGateway.ps1');
if not FileExists(SourceScriptPath) then
begin
ResultCode := 2;
Log('Local gateway cleanup script is missing: ' + SourceScriptPath);
Result := False;
Exit;
end;
if FileExists(TempScriptPath) then
DeleteFile(TempScriptPath);
if not CopyFile(SourceScriptPath, TempScriptPath, False) then
begin
ResultCode := 3;
Log('Failed to copy local gateway cleanup script to: ' + TempScriptPath);
Result := False;
Exit;
end;
Params :=
'-NoProfile -ExecutionPolicy Bypass -File ' + AddQuotes(TempScriptPath) +
' -AppRoot ' + AddQuotes(ExpandConstant('{app}')) +
' -DataDirectoryName ' + AddQuotes('{#MyInstallDir}') +
' -AutoStartName ' + AddQuotes('{#MyAutoStartName}') +
' -StartupTaskName ' + AddQuotes('{#MyStartupTaskName}') +
' -DistroName ' + AddQuotes('{#MyDistroName}');
Log('Running local gateway cleanup script from {tmp}.');
Result :=
Exec(
ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe'),
Params,
'',
SW_HIDE,
ewWaitUntilTerminated,
ResultCode);
if Result then
Log('Local gateway cleanup script exited with code ' + IntToStr(ResultCode) + '.')
else
Log('Failed to start local gateway cleanup script. System error: ' + IntToStr(ResultCode) + '.');
end;
procedure RunLocalGatewayCleanup;
var
ResultCode: Integer;
Retry: Boolean;
Started: Boolean;
begin
if not LocalGatewayCleanupRequested then
Exit;
LocalGatewayCleanupSucceeded := False;
repeat
Retry := False;
UninstallProgressForm.StatusLabel.Caption := 'Removing local WSL gateway...';
Started := RunLocalGatewayCleanupOnce(ResultCode);
if Started and (ResultCode = 0) then
begin
LocalGatewayCleanupSucceeded := True;
Log('Local gateway cleanup completed successfully.');
Exit;
end;
if UninstallSilent() then
begin
Log('Local gateway cleanup failed during silent uninstall; continuing without deleting generated state.');
Exit;
end;
Retry :=
MsgBox(
'OpenClaw could not remove the local WSL gateway.' + #13#10#13#10 +
'Exit code: ' + IntToStr(ResultCode) + #13#10#13#10 +
'Select Retry to try again, or Cancel to continue uninstalling OpenClaw and leave local gateway state on disk.',
mbError,
MB_RETRYCANCEL) = IDRETRY;
until not Retry;
Log('User continued uninstall after local gateway cleanup failed; generated state will be preserved.');
end;
procedure DeleteGeneratedAppState;
begin
if not LocalGatewayCleanupSucceeded then
Exit;
if DelTree(ExpandConstant('{app}'), True, True, True) then
Log('Deleted generated app state from {app}.')
else
Log('Generated app state in {app} could not be fully deleted; continuing uninstall.');
end;
procedure RemoveAppAutoStart;
var
ResultCode: Integer;
Started: Boolean;
begin
if RegDeleteValue(
HKCU,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
'{#MyAutoStartName}') then
Log('Removed {#MyAutoStartName} autostart registry value.')
else
Log('{#MyAutoStartName} autostart registry value already absent.');
Started :=
Exec(
ExpandConstant('{sys}\schtasks.exe'),
'/Delete /TN ' + AddQuotes('{#MyStartupTaskName}') + ' /F',
'',
SW_HIDE,
ewWaitUntilTerminated,
ResultCode);
if Started and (ResultCode = 0) then
Log('Removed {#MyStartupTaskName} startup task.')
else
Log('{#MyStartupTaskName} startup task already absent or unavailable.');
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
begin
RemoveAppAutoStart;
EnsureLocalGatewayCleanupChoice;
RunLocalGatewayCleanup;
end
else if CurUninstallStep = usPostUninstall then
begin
DeleteGeneratedAppState;
end;
end;