返回 DeepSeek-Reasonix
project.nsi
根目录 / desktop / build / windows / installer / project.nsi
1 Unicode true
2
3 ####
4 ## Reasonix per-user NSIS installer.
5 ##
6 ## This file is COMMITTED and customized (Wails leaves an existing project.nsi
7 ## untouched and only regenerates wails_tools.nsh). The customizations vs.
8 ## Wails' default template:
9 ##
10 ## 1. REQUEST_EXECUTION_LEVEL "user" + InstallDir under $LOCALAPPDATA - install
11 ## without administrator rights. This lets the auto-updater re-run a freshly
12 ## downloaded installer in a visible progress-only mode with no UAC prompt.
13 ## 2. Uninstall registry under HKCU (not HKLM). Wails' wails.writeUninstaller /
14 ## wails.deleteUninstaller macros hard-code HKLM, which a non-admin install
15 ## cannot write - so we inline HKCU versions below instead.
16 ## 3. InstallDir is remembered across updates via InstallDirRegKey +
17 ## InstallLocation (HKCU\...\Uninstall\InstallLocation). When upgrading from
18 ## a build that did not write InstallLocation yet, .onInit falls back to the
19 ## old DisplayIcon path before using the default. Without this, every release
20 ## forces the user back to %LOCALAPPDATA%\Programs\Reasonix even if they had
21 ## moved the install to a different drive (e.g. D:\Tools\Reasonix); the
22 ## auto-updater would overwrite the wrong dir, leaving the old install
23 ## orphaned.
24 ##
25 ## Everything else mirrors Wails' generated default. Defines below override the
26 ## ProjectInfo values that wails_tools.nsh would otherwise populate.
27 ####
28
29 ## Install per-user (no admin). Must be defined BEFORE including wails_tools.nsh,
30 ## which only sets the "admin" default when REQUEST_EXECUTION_LEVEL is undefined.
31 !define REQUEST_EXECUTION_LEVEL "user"
32
33 ####
34 ## Include the wails tools (auto-generated; provides INFO_* defines and the
35 ## wails.* macros used below).
36 ####
37 !include "wails_tools.nsh"
38 !include "FileFunc.nsh"
39 !include "LogicLib.nsh"
40
41 # The version information for this two must consist of 4 parts
42 VIProductVersion "${INFO_PRODUCTVERSION}.0"
43 VIFileVersion "${INFO_PRODUCTVERSION}.0"
44
45 VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
46 VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
47 VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
48 VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
49 VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
50 VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
51
52 # Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
53 ManifestDPIAware true
54
55 !include "MUI.nsh"
56
57 !define MUI_ICON "..\icon.ico"
58 !define MUI_UNICON "..\icon.ico"
59 # !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
60 !define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
61 !define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
62
63 !define MUI_PAGE_CUSTOMFUNCTION_PRE reasonix.skipSetupPageForUpdate
64 !insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
65 # !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
66 !define MUI_PAGE_CUSTOMFUNCTION_PRE reasonix.skipSetupPageForUpdate
67 !insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
68 !define MUI_PAGE_CUSTOMFUNCTION_SHOW reasonix.showUpdateProgress
69 !insertmacro MUI_PAGE_INSTFILES # Installing page.
70 !define MUI_PAGE_CUSTOMFUNCTION_PRE reasonix.skipFinishPageForUpdate
71 !insertmacro MUI_PAGE_FINISH # Finished installation page.
72
73 !insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
74
75 !insertmacro MUI_LANGUAGE "English"
76 !insertmacro MUI_LANGUAGE "SimpChinese"
77 !insertmacro MUI_LANGUAGE "TradChinese"
78
79 LangString reasonixUpdateTitle ${LANG_ENGLISH} "Updating Reasonix"
80 LangString reasonixUpdateTitle ${LANG_SIMPCHINESE} "正在更新 Reasonix"
81 LangString reasonixUpdateTitle ${LANG_TRADCHINESE} "正在更新 Reasonix"
82 LangString reasonixUpdateSubtitle ${LANG_ENGLISH} "Installing the verified update. Reasonix will restart automatically."
83 LangString reasonixUpdateSubtitle ${LANG_SIMPCHINESE} "正在安装已验证的更新,完成后 Reasonix 将自动重启。"
84 LangString reasonixUpdateSubtitle ${LANG_TRADCHINESE} "正在安裝已驗證的更新,完成後 Reasonix 將自動重新啟動。"
85
86 ## Preserve the first-pass generated uninstaller so the release workflow can
87 ## Authenticode-sign it together with the other installed payload files.
88 ## The second pass provides ARG_REASONIX_SIGNED_UNINSTALLER and embeds that
89 ## signed binary instead of generating another unsigned uninstaller.
90 !ifndef ARG_REASONIX_SIGNED_UNINSTALLER
91 !uninstfinalize 'cmd.exe /C copy /Y "%1" "reasonix-uninstall.exe" >NUL'
92 !endif
93 #!finalize 'signtool --file "%1"'
94
95 Name "${INFO_PRODUCTNAME}"
96 OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
97 !define REASONIX_DEFAULT_INSTALLDIR "$LOCALAPPDATA\Programs\${INFO_PRODUCTNAME}"
98 !define REASONIX_UPDATE_HELPER "reasonix-update-helper.exe"
99 !define REASONIX_GUARD "reasonix-guard.exe"
100 !define REASONIX_LAUNCHER "reasonix-launcher.exe"
101 !define REASONIX_CLI "reasonix-cli.exe"
102 !define REASONIX_PORTABLE_ENTRY "Reasonix.exe"
103 !define REASONIX_LAYOUT_INSTALLER "reasonix-layout-installer.exe"
104 !define REASONIX_PAYLOAD_MANIFEST "reasonix-payload.json"
105 !define REASONIX_PAYLOAD_SIGNATURE "reasonix-payload.json.minisig"
106 !define REASONIX_LEGACY_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\Reasonix"
107 !define REASONIX_LEGACY_PRODUCT_KEY "Software\reasonix\Reasonix"
108 !define REASONIX_UNLOCK_RETRIES 60
109 Var ReasonixUpdateMode
110 Var ReasonixStageMode
111 InstallDirRegKey HKCU "${UNINST_KEY}" "InstallLocation" # Reuse the previous install path on update; .onInit falls back to the default on first install.
112 InstallDir "${REASONIX_DEFAULT_INSTALLDIR}" # Per-user install location (no admin rights required).
113 ShowInstDetails show # This will always show the installation details.
114
115 ####
116 ## Per-user uninstaller registry (HKCU). Replaces wails.writeUninstaller /
117 ## wails.deleteUninstaller, which write HKLM and would fail without admin rights.
118 ####
119 !macro reasonix.writeUninstaller
120 !ifdef ARG_REASONIX_SIGNED_UNINSTALLER
121 File "/oname=uninstall.exe" "${ARG_REASONIX_SIGNED_UNINSTALLER}"
122 !else
123 WriteUninstaller "$INSTDIR\uninstall.exe"
124 !endif
125
126 WriteRegStr HKCU "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
127 WriteRegStr HKCU "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
128 WriteRegStr HKCU "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
129 !if /FileExists "${REASONIX_LAUNCHER}"
130 WriteRegStr HKCU "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${REASONIX_LAUNCHER}"
131 !else
132 WriteRegStr HKCU "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
133 !endif
134 WriteRegStr HKCU "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
135 WriteRegStr HKCU "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
136 # Persist the resolved install path so a subsequent update picks it up
137 # via InstallDirRegKey above. Without this, every release would force the
138 # user back to %LOCALAPPDATA%\Programs\Reasonix even if they had moved
139 # the install to a different drive (e.g. D:\Tools\Reasonix). The auto-
140 # updater trusts this persisted path, so it has to be present before the
141 # visible progress-only re-install.
142 WriteRegStr HKCU "${UNINST_KEY}" "InstallLocation" "$INSTDIR"
143
144 ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
145 IntFmt $0 "0x%08X" $0
146 WriteRegDWORD HKCU "${UNINST_KEY}" "EstimatedSize" "$0"
147 !macroend
148
149 ; Tauri 0.53 separately persisted $INSTDIR under its manufacturer/product key
150 ; and restores that value before every later install. Clear only a same-root
151 ; value so re-running 0.53 cannot overwrite the current uninstaller; preserve a
152 ; genuinely separate legacy installation. If this cleanup fails, retain the old
153 ; uninstall alias so a later update can retry the migration.
154 !macro reasonix.deleteLegacyInstallerStateIfOwned
155 StrCpy $1 "1"
156 ClearErrors
157 ReadRegStr $0 HKCU "${REASONIX_LEGACY_PRODUCT_KEY}" ""
158 ${If} $0 == "$INSTDIR"
159 ClearErrors
160 DeleteRegValue HKCU "${REASONIX_LEGACY_PRODUCT_KEY}" ""
161 ${If} ${Errors}
162 StrCpy $1 "0"
163 ${EndIf}
164 ${ElseIf} $0 == "$\"$INSTDIR$\""
165 ClearErrors
166 DeleteRegValue HKCU "${REASONIX_LEGACY_PRODUCT_KEY}" ""
167 ${If} ${Errors}
168 StrCpy $1 "0"
169 ${EndIf}
170 ${EndIf}
171
172 ${If} $1 == "1"
173 ClearErrors
174 ReadRegStr $0 HKCU "${REASONIX_LEGACY_UNINST_KEY}" "InstallLocation"
175 ${If} $0 == "$INSTDIR"
176 DeleteRegKey HKCU "${REASONIX_LEGACY_UNINST_KEY}"
177 ${ElseIf} $0 == "$\"$INSTDIR$\""
178 DeleteRegKey HKCU "${REASONIX_LEGACY_UNINST_KEY}"
179 ${Else}
180 ClearErrors
181 ReadRegStr $0 HKCU "${REASONIX_LEGACY_UNINST_KEY}" "UninstallString"
182 ${If} $0 == "$INSTDIR\uninstall.exe"
183 DeleteRegKey HKCU "${REASONIX_LEGACY_UNINST_KEY}"
184 ${ElseIf} $0 == "$\"$INSTDIR\uninstall.exe$\""
185 DeleteRegKey HKCU "${REASONIX_LEGACY_UNINST_KEY}"
186 ${EndIf}
187 ${EndIf}
188 ${EndIf}
189 !macroend
190
191 !macro reasonix.deleteUninstaller
192 Delete "$INSTDIR\uninstall.exe"
193 DeleteRegKey HKCU "${UNINST_KEY}"
194 !macroend
195
196 Function .onInit
197 !insertmacro wails.checkArchitecture
198
199 ; The helper passes /REASONIXUPDATE=1 and a final /D=<current directory>.
200 ; This mode remains visible but skips every page that could change the
201 ; destination, then closes automatically after the file copy so the helper
202 ; can relaunch Reasonix. A normal manual installer keeps the full wizard.
203 StrCpy $ReasonixUpdateMode "0"
204 StrCpy $ReasonixStageMode "0"
205 ${GetParameters} $R0
206 ClearErrors
207 ${GetOptions} $R0 "/REASONIXUPDATE=" $R1
208 IfErrors reasonix_update_mode_done
209 StrCmp $R1 "1" 0 reasonix_update_mode_done
210 StrCpy $ReasonixUpdateMode "1"
211
212 reasonix_update_mode_done:
213 ClearErrors
214 ${GetOptions} $R0 "/REASONIXSTAGE=" $R2
215 IfErrors reasonix_stage_mode_done
216 StrCmp $R2 "1" 0 reasonix_stage_mode_done
217 StrCpy $ReasonixStageMode "1"
218
219 reasonix_stage_mode_done:
220
221 ; InstallDirRegKey leaves $INSTDIR empty when the InstallLocation value is
222 ; missing. Older installers still wrote DisplayIcon, so use its parent folder
223 ; as a compatibility bridge before falling back to the per-user default.
224 StrCmp $INSTDIR "" 0 done
225 ClearErrors
226 ReadRegStr $0 HKCU "${UNINST_KEY}" "DisplayIcon"
227 IfErrors legacy_location
228 StrCmp $0 "" legacy_location
229 ${GetParent} "$0" $INSTDIR
230 StrCmp $INSTDIR "" legacy_location done
231
232 legacy_location:
233 ; Tauri 0.53 used a different uninstall key and may have stored the selected
234 ; directory with surrounding quotes (for example "D:\Reasonix"). Reuse it
235 ; only while its uninstaller still exists so a stale registry value cannot
236 ; redirect the repair installer into an unrelated directory.
237 ClearErrors
238 ReadRegStr $0 HKCU "${REASONIX_LEGACY_UNINST_KEY}" "InstallLocation"
239 IfErrors legacy_uninstaller
240 StrCmp $0 "" legacy_uninstaller
241 StrCpy $1 $0 1
242 StrCmp $1 "$\"" 0 legacy_location_ready
243 StrCpy $1 $0 1 -1
244 StrCmp $1 "$\"" 0 legacy_location_ready
245 StrCpy $0 $0 -1 1
246
247 legacy_location_ready:
248 IfFileExists "$0\uninstall.exe" 0 legacy_uninstaller
249 StrCpy $INSTDIR $0
250 Goto done
251
252 legacy_uninstaller:
253 ClearErrors
254 ReadRegStr $0 HKCU "${REASONIX_LEGACY_UNINST_KEY}" "UninstallString"
255 IfErrors fallback
256 StrCmp $0 "" fallback
257 StrCpy $1 $0 1
258 StrCmp $1 "$\"" 0 legacy_uninstaller_ready
259 StrCpy $1 $0 1 -1
260 StrCmp $1 "$\"" 0 legacy_uninstaller_ready
261 StrCpy $0 $0 -1 1
262
263 legacy_uninstaller_ready:
264 IfFileExists "$0" 0 fallback
265 ${GetParent} "$0" $INSTDIR
266 StrCmp $INSTDIR "" fallback done
267
268 fallback:
269 StrCpy $INSTDIR "${REASONIX_DEFAULT_INSTALLDIR}"
270 done:
271 FunctionEnd
272
273 Function reasonix.skipSetupPageForUpdate
274 StrCmp $ReasonixUpdateMode "1" 0 reasonix_show_setup_page
275 Abort
276
277 reasonix_show_setup_page:
278 FunctionEnd
279
280 Function reasonix.showUpdateProgress
281 StrCmp $ReasonixUpdateMode "1" 0 reasonix_update_progress_done
282 !insertmacro MUI_HEADER_TEXT "$(reasonixUpdateTitle)" "$(reasonixUpdateSubtitle)"
283 SetDetailsView hide
284 SetAutoClose true
285 BringToFront
286
287 reasonix_update_progress_done:
288 FunctionEnd
289
290 Function reasonix.skipFinishPageForUpdate
291 StrCmp $ReasonixUpdateMode "1" 0 reasonix_show_finish_page
292 Abort
293
294 reasonix_show_finish_page:
295 FunctionEnd
296
297 Function reasonix.waitForExecutableUnlock
298 StrCpy $0 0
299
300 retry:
301 IfFileExists "$INSTDIR\${PRODUCT_EXECUTABLE}" 0 check_versioned_target
302 ClearErrors
303 FileOpen $1 "$INSTDIR\${PRODUCT_EXECUTABLE}" a
304 IfErrors locked
305 FileClose $1
306
307 check_versioned_target:
308 ; A same-version recovery install replaces this directory transactionally.
309 ; Detect the running active binary before asking the Go activator to rename it.
310 IfFileExists "$INSTDIR\versions\v${INFO_PRODUCTVERSION}\${PRODUCT_EXECUTABLE}" 0 check_guard
311 ClearErrors
312 FileOpen $1 "$INSTDIR\versions\v${INFO_PRODUCTVERSION}\${PRODUCT_EXECUTABLE}" a
313 IfErrors locked
314 FileClose $1
315
316 check_guard:
317 IfFileExists "$INSTDIR\${REASONIX_GUARD}" 0 check_launcher
318 ClearErrors
319 FileOpen $1 "$INSTDIR\${REASONIX_GUARD}" a
320 IfErrors locked
321 FileClose $1
322
323 check_launcher:
324 IfFileExists "$INSTDIR\${REASONIX_LAUNCHER}" 0 check_cli
325 ClearErrors
326 FileOpen $1 "$INSTDIR\${REASONIX_LAUNCHER}" a
327 IfErrors locked
328 FileClose $1
329
330 check_cli:
331 IfFileExists "$INSTDIR\${REASONIX_CLI}" 0 check_portable_entry
332 ClearErrors
333 FileOpen $1 "$INSTDIR\${REASONIX_CLI}" a
334 IfErrors locked
335 FileClose $1
336
337 check_portable_entry:
338 IfFileExists "$INSTDIR\${REASONIX_PORTABLE_ENTRY}" 0 done
339 ClearErrors
340 FileOpen $1 "$INSTDIR\${REASONIX_PORTABLE_ENTRY}" a
341 IfErrors locked
342 FileClose $1
343 Goto done
344
345 locked:
346 IntOp $0 $0 + 1
347 IntCmp $0 ${REASONIX_UNLOCK_RETRIES} failed 0 0
348 Sleep 1000
349 Goto retry
350
351 failed:
352 IfSilent silent interactive
353
354 interactive:
355 MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "Reasonix is still running. Close Reasonix, then click Retry to continue the installation." IDRETRY retry IDCANCEL abort
356 Goto retry
357
358 silent:
359 SetErrorLevel 1618
360
361 abort:
362 Abort "Reasonix is still running. Close Reasonix and run the installer again."
363
364 done:
365 FunctionEnd
366
367 Section
368 !insertmacro wails.setShellContext
369
370 ; /REASONIXSTAGE=1: flat six-member payload for 1.18–1.19.1 helpers (and
371 ; the new helper's staging extract). Do not write shortcuts/uninstaller.
372 ; Normal install: versioned-v1 layout under versions/v${INFO_PRODUCTVERSION}/
373 ; with a permanent thin launcher at InstallRoot. Guard is only present in
374 ; STAGE payloads (as the one-shot legacy migrator) and is not persisted on
375 ; a normal install.
376 StrCmp $ReasonixStageMode "1" reasonix_stage_payload
377 !insertmacro wails.webview2runtime
378 Call reasonix.waitForExecutableUnlock
379 Goto reasonix_normal_install
380
381 reasonix_stage_payload:
382 SetOutPath $INSTDIR
383 !if /FileExists "${REASONIX_PAYLOAD_MANIFEST}"
384 File "/oname=${REASONIX_PAYLOAD_MANIFEST}" "${REASONIX_PAYLOAD_MANIFEST}"
385 !endif
386 !if /FileExists "${REASONIX_PAYLOAD_SIGNATURE}"
387 File "/oname=${REASONIX_PAYLOAD_SIGNATURE}" "${REASONIX_PAYLOAD_SIGNATURE}"
388 !endif
389 !insertmacro wails.files
390 !if /FileExists "${REASONIX_UPDATE_HELPER}"
391 File "/oname=${REASONIX_UPDATE_HELPER}" "${REASONIX_UPDATE_HELPER}"
392 !endif
393 !if /FileExists "${REASONIX_GUARD}"
394 File "/oname=${REASONIX_GUARD}" "${REASONIX_GUARD}"
395 !endif
396 !if /FileExists "${REASONIX_LAUNCHER}"
397 File "/oname=${REASONIX_LAUNCHER}" "${REASONIX_LAUNCHER}"
398 !endif
399 !if /FileExists "${REASONIX_CLI}"
400 File "/oname=${REASONIX_CLI}" "${REASONIX_CLI}"
401 !endif
402 Goto reasonix_section_done
403
404 reasonix_normal_install:
405 ; Extract into an install-local temporary directory, then let the signed Go
406 ; activator validate the complete release unit, transactionally publish the
407 ; version/root entries, and strictly atomically replace current.json last.
408 ; The normal/recovery installer therefore shares the same commit protocol as
409 ; automatic updates instead of writing live files or current.json in place.
410 System::Call 'kernel32::GetCurrentProcessId() i .R8'
411 CreateDirectory "$INSTDIR\versions"
412 StrCpy $R9 "$INSTDIR\versions\.installer-v${INFO_PRODUCTVERSION}-$R8"
413 RMDir /r "$R9"
414 CreateDirectory "$R9"
415 SetOutPath "$R9"
416 !insertmacro wails.files
417 !if /FileExists "${REASONIX_UPDATE_HELPER}"
418 File "/oname=${REASONIX_UPDATE_HELPER}" "${REASONIX_UPDATE_HELPER}"
419 !else
420 !warning "${REASONIX_UPDATE_HELPER} was not found; Windows auto-update will fail safely until the helper is installed."
421 !endif
422 !if /FileExists "${REASONIX_CLI}"
423 File "/oname=${REASONIX_CLI}" "${REASONIX_CLI}"
424 !else
425 !warning "${REASONIX_CLI} was not found; remote upload installation will be unavailable."
426 !endif
427 !if /FileExists "${REASONIX_LAUNCHER}"
428 File "/oname=${REASONIX_LAUNCHER}" "${REASONIX_LAUNCHER}"
429 !endif
430
431 SetOutPath "$PLUGINSDIR"
432 !if /FileExists "${REASONIX_GUARD}"
433 File "/oname=${REASONIX_LAYOUT_INSTALLER}" "${REASONIX_GUARD}"
434 !else
435 !error "${REASONIX_GUARD} was not found; normal installs require the signed layout activator."
436 !endif
437 DetailPrint "Reasonix layout activator output:"
438 nsExec::ExecToLog /OEM '"$PLUGINSDIR\${REASONIX_LAYOUT_INSTALLER}" --install-root "$INSTDIR" --version "v${INFO_PRODUCTVERSION}" --activate-staging "$R9" --no-relaunch'
439 Pop $0
440 StrCmp $0 "0" reasonix_layout_activated
441 DetailPrint "Reasonix layout activation failed with exit code $0; the previous version remains active."
442 RMDir /r "$R9"
443 SetErrorLevel 1
444 Abort "Reasonix could not activate the verified release. The previous version was left unchanged."
445
446 reasonix_layout_activated:
447 RMDir /r "$R9"
448 SetOutPath "$INSTDIR"
449
450 ; Remove flat leftovers from prior 1.18–1.19 installs when overwriting.
451 Delete "$INSTDIR\${PRODUCT_EXECUTABLE}"
452 Delete "$INSTDIR\${REASONIX_GUARD}"
453 Delete "$INSTDIR\${REASONIX_UPDATE_HELPER}"
454
455 !if /FileExists "${REASONIX_LAUNCHER}"
456 ; Keep both target and icon on the stable launcher. Pointing IconLocation at
457 ; versions\vX\reasonix-desktop.exe leaves a blank shortcut as soon as version
458 ; retention removes that directory after a later update.
459 CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${REASONIX_LAUNCHER}" "" "$INSTDIR\${REASONIX_LAUNCHER}" 0
460 CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${REASONIX_LAUNCHER}" "" "$INSTDIR\${REASONIX_LAUNCHER}" 0
461 !else
462 CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\versions\v${INFO_PRODUCTVERSION}\${PRODUCT_EXECUTABLE}"
463 CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\versions\v${INFO_PRODUCTVERSION}\${PRODUCT_EXECUTABLE}"
464 !endif
465
466 !insertmacro wails.associateFiles
467 !insertmacro wails.associateCustomProtocols
468 !insertmacro reasonix.writeUninstaller
469 !insertmacro reasonix.deleteLegacyInstallerStateIfOwned
470
471 reasonix_section_done:
472 SectionEnd
473
474 Section "uninstall"
475 !insertmacro wails.setShellContext
476
477 RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
478
479 ; Precision uninstall: flat leftovers, thin entry points, and version trees.
480 Delete "$INSTDIR\${PRODUCT_EXECUTABLE}"
481 Delete "$INSTDIR\${REASONIX_UPDATE_HELPER}"
482 Delete "$INSTDIR\${REASONIX_GUARD}"
483 Delete "$INSTDIR\${REASONIX_LAUNCHER}"
484 Delete "$INSTDIR\${REASONIX_CLI}"
485 Delete "$INSTDIR\${REASONIX_PORTABLE_ENTRY}"
486 Delete "$INSTDIR\current.json"
487 RMDir /r "$INSTDIR\versions"
488
489 Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
490 Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
491
492 !insertmacro wails.unassociateFiles
493 !insertmacro wails.unassociateCustomProtocols
494
495 !insertmacro reasonix.deleteUninstaller
496 !insertmacro reasonix.deleteLegacyInstallerStateIfOwned
497
498 ; Only remove the installation directory if it is empty to prevent data loss
499 RMDir $INSTDIR
500 SectionEnd
501
501 lines Plain Text