Bug Description
After upgrading a 64-bit NSIS app (installed in C:\Program Files\App), the uninstaller's $INSTDIR resolves to C:\Program Files (x86)\App instead of the correct 64-bit path. This causes the uninstall to silently fail — the app directory is not removed.
Fresh install → uninstall works correctly. Only the upgrade → uninstall path is broken.
Steps to Reproduce
- Install a 64-bit electron-builder NSIS app (installs to
C:\Program Files\App)
- Upgrade to a newer version (upgrade succeeds, correct path)
- Uninstall the app
- App directory remains at
C:\Program Files\App — uninstaller targeted C:\Program Files (x86)\App
Evidence
Uninstall log showing $INSTDIR wrong after upgrade:
# During UPDATE — old uninstaller runs with correct path:
Start CustomRemoveFiles 3.41.0
Command: "C:\Program Files\Remote.It\resources\remoteit" agent uninstall
Result Code: 0
RMDir C:\Program Files\Remote.It
# Later UNINSTALL — $INSTDIR is wrong:
Start CustomRemoveFiles 3.45.2
Command: "C:\Program Files (x86)\Remote.It\resources\remoteit" agent uninstall
Result Code: error
RMDir C:\Program Files (x86)\Remote.It ← wrong path, app left behind
The registry has the correct value in the 64-bit view:
HKEY_LOCAL_MACHINE\SOFTWARE\{app-guid}
InstallLocation REG_SZ C:\Program Files\Remote.It
No entry exists under WOW6432Node (32-bit view).
Analysis
un.onInit in uninstaller.nsh calls check64BitAndSetRegView → initMultiUser → setInstallModePerAllUsers, which should read InstallLocation from the 64-bit registry and set $INSTDIR correctly. Despite the registry containing the correct value under the 64-bit view, $INSTDIR defaults to $PROGRAMFILES (the 32-bit path) in the upgrade→uninstall flow.
Notably, during BUILD_UNINSTALLER in installer.nsi, the .onInit function skips check64BitAndSetRegView entirely:
Function .onInit
!ifmacrodef preInit
!insertmacro preInit
!endif
!ifdef BUILD_UNINSTALLER
WriteUninstaller "${UNINSTALLER_OUT_FILE}"
!insertmacro quitSuccess ; ← exits here
!else
!insertmacro check64BitAndSetRegView ; ← never reached for uninstaller build
!insertmacro initMultiUser
!endif
FunctionEnd
This may contribute to the uninstaller binary's default $INSTDIR being set to the 32-bit path.
Workaround
We worked around this by explicitly reading the registry at the start of our customRemoveFiles macro:
SetRegView 64
ReadRegStr $0 HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation
${ifNot} $0 == ""
StrCpy $INSTDIR $0
${endIf}
Log confirming the workaround corrects the path:
INSTDIR before fix: C:\Program Files (x86)\Remote.It
INSTDIR after fix: C:\Program Files\Remote.It
Environment
- electron-builder: 26.8.1
- OS: Windows 11 x64
- NSIS config:
oneClick: false, perMachine: true, allowToChangeInstallationDirectory: true
- Architecture: x64 app (
APP_64 defined)
Expected Behavior
$INSTDIR in the uninstaller should resolve to the actual install location (C:\Program Files\App) regardless of whether the app was freshly installed or upgraded.
Bug Description
After upgrading a 64-bit NSIS app (installed in
C:\Program Files\App), the uninstaller's$INSTDIRresolves toC:\Program Files (x86)\Appinstead of the correct 64-bit path. This causes the uninstall to silently fail — the app directory is not removed.Fresh install → uninstall works correctly. Only the upgrade → uninstall path is broken.
Steps to Reproduce
C:\Program Files\App)C:\Program Files\App— uninstaller targetedC:\Program Files (x86)\AppEvidence
Uninstall log showing
$INSTDIRwrong after upgrade:The registry has the correct value in the 64-bit view:
No entry exists under
WOW6432Node(32-bit view).Analysis
un.onInitinuninstaller.nshcallscheck64BitAndSetRegView→initMultiUser→setInstallModePerAllUsers, which should readInstallLocationfrom the 64-bit registry and set$INSTDIRcorrectly. Despite the registry containing the correct value under the 64-bit view,$INSTDIRdefaults to$PROGRAMFILES(the 32-bit path) in the upgrade→uninstall flow.Notably, during
BUILD_UNINSTALLERininstaller.nsi, the.onInitfunction skipscheck64BitAndSetRegViewentirely:This may contribute to the uninstaller binary's default
$INSTDIRbeing set to the 32-bit path.Workaround
We worked around this by explicitly reading the registry at the start of our
customRemoveFilesmacro:Log confirming the workaround corrects the path:
Environment
oneClick: false,perMachine: true,allowToChangeInstallationDirectory: trueAPP_64defined)Expected Behavior
$INSTDIRin the uninstaller should resolve to the actual install location (C:\Program Files\App) regardless of whether the app was freshly installed or upgraded.