Skip to content

Commit 60334f9

Browse files
authored
feat(bundler/NSIS): uninstall previous wix if exist, closes #6859 (#6933)
1 parent 0f707d2 commit 60334f9

File tree

2 files changed

+96
-20
lines changed

2 files changed

+96
-20
lines changed

.changes/nsis-uninstall-wix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'tauri-bundler': 'minor'
3+
---
4+
5+
NSIS installer will now check if a previous WiX `.msi` installation exist and will prompt users to uninstall it.

tooling/bundler/src/bundle/windows/templates/installer.nsi

Lines changed: 91 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
Var AppStartMenuFolder
2-
Var ReinstallPageCheck
3-
41
!include MUI2.nsh
52
!include FileFunc.nsh
63
!include x64.nsh
@@ -44,11 +41,12 @@ VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
4441
VIAddVersionKey "FileVersion" "${VERSION}"
4542
VIAddVersionKey "ProductVersion" "${VERSION}"
4643

44+
; Plugins path, currently exists for linux only
4745
!if "${PLUGINSPATH}" != ""
4846
!addplugindir "${PLUGINSPATH}"
4947
!endif
5048

51-
49+
; Handle install mode, `perUser`, `perMachine` or `both`
5250
!if "${INSTALLMODE}" == "perMachine"
5351
RequestExecutionLevel highest
5452
!endif
@@ -74,14 +72,17 @@ VIAddVersionKey "ProductVersion" "${VERSION}"
7472
!include MultiUser.nsh
7573
!endif
7674

75+
; installer icon
7776
!if "${INSTALLERICON}" != ""
7877
!define MUI_ICON "${INSTALLERICON}"
7978
!endif
8079

80+
; installer sidebar image
8181
!if "${SIDEBARIMAGE}" != ""
8282
!define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}"
8383
!endif
8484

85+
; installer header image
8586
!if "${HEADERIMAGE}" != ""
8687
!define MUI_HEADERIMAGE
8788
!define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
@@ -92,26 +93,65 @@ VIAddVersionKey "ProductVersion" "${VERSION}"
9293
!define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}"
9394
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
9495

95-
; Installer pages, must be ordered as they appear
96+
; Installer pages, must be ordered as they should appear to the user
97+
;
98+
; 1. Welcome Page
9699
!insertmacro MUI_PAGE_WELCOME
100+
101+
; 2. License Page (if defined)
97102
!if "${LICENSE}" != ""
98103
!insertmacro MUI_PAGE_LICENSE "${LICENSE}"
99104
!endif
105+
106+
; 3. Install mode (if it is set to `both`)
100107
!if "${INSTALLMODE}" == "both"
101108
!insertmacro MULTIUSER_PAGE_INSTALLMODE
102109
!endif
103110

104-
; Custom page to ask user if he wants to reinstall/uninstall
111+
112+
; 4. Custom page to ask user if he wants to reinstall/uninstall
113+
; only if a previous installtion was detected
114+
Var ReinstallPageCheck
105115
Page custom PageReinstall PageLeaveReinstall
106116
Function PageReinstall
117+
; Uninstall previous WiX installation if exists.
118+
;
119+
; A WiX installer stores the isntallation info in registry
120+
; using a UUID and so we have to loop through all keys under
121+
; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
122+
; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER}
123+
;
124+
; This has a potentional issue that there maybe another installation that matches
125+
; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer,
126+
; however, this should be fine since the user will have to confirm the uninstallation
127+
; and they can chose to abort it if doesn't make sense.
128+
StrCpy $0 0
129+
wix_loop:
130+
EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0
131+
StrCmp $1 "" wix_done ; Exit loop if there is no more keys to loop on
132+
IntOp $0 $0 + 1
133+
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName"
134+
ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher"
135+
StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop
136+
StrCpy $R5 "wix"
137+
StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1"
138+
Goto compare_version
139+
wix_done:
140+
107141
; Check if there is an existing installation, if not, abort the reinstall page
108142
ReadRegStr $R0 SHCTX "${UNINSTKEY}" ""
109143
ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
110144
${IfThen} "$R0$R1" == "" ${|} Abort ${|}
111145

112-
; Compare this installar version with the existing installation and modify the messages presented to the user accordingly
146+
; Compare this installar version with the existing installation
147+
; and modify the messages presented to the user accordingly
148+
compare_version:
113149
StrCpy $R4 "$(older)"
114-
ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion"
150+
${If} $R5 == "wix"
151+
ReadRegStr $R0 HKLM "$R6" "DisplayVersion"
152+
${Else}
153+
ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion"
154+
${EndIf}
115155
${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|}
116156

117157
nsis_tauri_utils::SemverCompare "${VERSION}" $R0
@@ -186,7 +226,6 @@ Function PageReinstallUpdateSelection
186226
${Else}
187227
StrCpy $ReinstallPageCheck 2
188228
${EndIf}
189-
190229
FunctionEnd
191230
Function PageLeaveReinstall
192231
${NSD_GetState} $R2 $R1
@@ -197,17 +236,21 @@ Function PageLeaveReinstall
197236
;
198237
; $R1 holds the radio buttons state. its meaning is dependant on the context
199238
StrCmp $R0 "1" 0 +2 ; Existing install is not the same version?
200-
StrCmp $R1 "1" reinst_uninstall reinst_done
201-
StrCmp $R1 "1" reinst_done ; Same version, skip to add/reinstall components?
239+
StrCmp $R1 "1" reinst_uninstall reinst_done ; $R1 == "1", then user chose to uninstall existing version, otherwise skip uninstalling
240+
StrCmp $R1 "1" reinst_done ; Same version? skip uninstalling
202241

203242
reinst_uninstall:
204-
ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
205-
ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
206-
207243
HideWindow
208-
209244
ClearErrors
210-
ExecWait '$R1 _?=$4' $0
245+
246+
${If} $R5 == "wix"
247+
ReadRegStr $R1 HKLM "$R6" "UninstallString"
248+
ExecWait '$R1' $0
249+
${Else}
250+
ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
251+
ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
252+
ExecWait '$R1 _?=$4' $0
253+
${EndIf}
211254

212255
BringToFront
213256

@@ -232,14 +275,22 @@ Function PageLeaveReinstall
232275
reinst_done:
233276
FunctionEnd
234277

278+
; 5. Choose install directoy page
235279
!insertmacro MUI_PAGE_DIRECTORY
280+
281+
; 6. Start menu shortcut page
282+
Var AppStartMenuFolder
236283
!insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder
284+
285+
; 7. Installation page
237286
!insertmacro MUI_PAGE_INSTFILES
238287

288+
; 8. Finish page
289+
;
239290
; Don't auto jump to finish page after installation page,
240291
; because the installation page has useful info that can be used debug any issues with the installer.
241292
!define MUI_FINISHPAGE_NOAUTOCLOSE
242-
; Use show readme button in the finish page to create a desktop shortcut
293+
; Use show readme button in the finish page as a button create a desktop shortcut
243294
!define MUI_FINISHPAGE_SHOWREADME
244295
!define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)"
245296
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut
@@ -252,6 +303,7 @@ FunctionEnd
252303
!insertmacro MUI_PAGE_FINISH
253304

254305
; Uninstaller Pages
306+
; 1. Confirm uninstall page
255307
Var DeleteAppDataCheckbox
256308
Var DeleteAppDataCheckboxState
257309
!define /ifndef WS_EX_LAYOUTRTL 0x00400000
@@ -273,6 +325,7 @@ Function un.ConfirmLeave
273325
FunctionEnd
274326
!insertmacro MUI_UNPAGE_CONFIRM
275327

328+
; 2. Uninstalling Page
276329
!insertmacro MUI_UNPAGE_INSTFILES
277330

278331
;Languages
@@ -295,9 +348,19 @@ Function .onInit
295348
SetShellVarContext all
296349
!endif
297350

351+
${If} ${RunningX64}
352+
!if "${ARCH}" == "x64"
353+
SetRegView 64
354+
!else if "${ARCH}" == "arm64"
355+
SetRegView 64
356+
!else
357+
SetRegView 32
358+
!endif
359+
${EndIf}
360+
298361
${If} $INSTDIR == ""
362+
; Set default install location
299363
!if "${INSTALLMODE}" == "perMachine"
300-
; Set default install location
301364
${If} ${RunningX64}
302365
!if "${ARCH}" == "x64"
303366
StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}"
@@ -349,9 +412,7 @@ Section Webview2
349412
StrCmp $4 "" 0 done
350413
StrCmp $5 "" 0 done
351414

352-
;--------------------------------
353415
; Webview2 install modes
354-
355416
!if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper"
356417
Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
357418
DetailPrint "$(webview2Downloading)"
@@ -494,6 +555,16 @@ Function .onInstSuccess
494555
FunctionEnd
495556

496557
Function un.onInit
558+
${If} ${RunningX64}
559+
!if "${ARCH}" == "x64"
560+
SetRegView 64
561+
!else if "${ARCH}" == "arm64"
562+
SetRegView 64
563+
!else
564+
SetRegView 32
565+
!endif
566+
${EndIf}
567+
497568
!if "${INSTALLMODE}" == "both"
498569
!insertmacro MULTIUSER_UNINIT
499570
!endif

0 commit comments

Comments
 (0)