Skip to content

Commit d90c9d6

Browse files
committed
fix(nsis): repair upgrade copy — taskkill without USERNAME filter, drop force-current-user
Elevated installer + taskkill /FI USERNAME= often left the app running so CopyFiles to Program Files failed. Remove the filter; add second kill/wait pass before copy, longer poll, short post-wait sleep for DLL handles. customInstallMode no longer forces per-user install (conflicts with perMachine / Program Files). Made-with: Cursor
1 parent ccddd42 commit d90c9d6

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

app/windows/installer-hooks.nsi

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,27 +136,31 @@ hspWaitPackagedPoll:
136136
Call HspAnyPackagedExeRunning
137137
IntCmp $0 0 hspWaitPackagedDone
138138
IntOp $R8 $R8 + 1
139-
IntCmp $R8 400 0 0 hspWaitPackagedDone
139+
IntCmp $R8 600 0 0 hspWaitPackagedDone
140140
Sleep 50
141141
Goto hspWaitPackagedPoll
142142
hspWaitPackagedDone:
143+
; Let handles on DLLs under $INSTDIR release (Program Files upgrades).
144+
Sleep 400
143145
FunctionEnd
144146

145147
Function HspKillPackagedAppProcesses
146148
; Named exes (Electron main + helpers + legacy names). /F /T = force + child processes.
147-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME}.exe" /FI "USERNAME eq %USERNAME%"`
149+
; Do NOT use /FI USERNAME=… — when the installer is elevated, that filter often misses user
150+
; sessions and the app stays running, so CopyFiles to Program Files fails with "Can't modify".
151+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME}.exe"`
148152
Pop $R9
149-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper.exe" /FI "USERNAME eq %USERNAME%"`
153+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper.exe"`
150154
Pop $R9
151-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (GPU).exe" /FI "USERNAME eq %USERNAME%"`
155+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (GPU).exe"`
152156
Pop $R9
153-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (Renderer).exe" /FI "USERNAME eq %USERNAME%"`
157+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (Renderer).exe"`
154158
Pop $R9
155-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (Plugin).exe" /FI "USERNAME eq %USERNAME%"`
159+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${PRODUCT_FILENAME} Helper (Plugin).exe"`
156160
Pop $R9
157-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${APP_PACKAGE_NAME}.exe" /FI "USERNAME eq %USERNAME%"`
161+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${APP_PACKAGE_NAME}.exe"`
158162
Pop $R9
159-
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${HSP_ALT_MAIN_EXE}" /FI "USERNAME eq %USERNAME%"`
163+
nsExec::Exec `%SYSTEMROOT%\System32\cmd.exe /c taskkill /F /T /IM "${HSP_ALT_MAIN_EXE}"`
160164
Pop $R9
161165
; Anything still running from $INSTDIR (crashpad, future helper renames, etc.). Same approach as app-builder _KILL_PROCESS via CIM.
162166
StrCpy $R7 "$INSTDIR"
@@ -171,6 +175,9 @@ Function HspKillBeforeCopy
171175
DetailPrint "[installer] unlock install dir before copy (attempt $R1)"
172176
Call HspKillPackagedAppProcesses
173177
Call HspWaitUntilPackagedProcessesGone
178+
; Second pass: elevation can miss user processes on first taskkill; retry once.
179+
Call HspKillPackagedAppProcesses
180+
Call HspWaitUntilPackagedProcessesGone
174181
FunctionEnd
175182

176183
Function HspFinishPageShow
@@ -237,8 +244,8 @@ FunctionEnd
237244
!macroend
238245

239246
!macro customInstallMode
240-
!insertmacro HspInstallDetailPrint "[installer] forcing current-user install mode"
241-
StrCpy $isForceCurrentInstall "1"
247+
; Leave install mode to electron-builder (perMachine in package.json → Program Files).
248+
; Forcing $isForceCurrentInstall breaks INSTALL_MODE_PER_ALL_USERS_REQUIRED / per-machine builds.
242249
!macroend
243250

244251
; Installer only. Uninstaller defines BUILD_UNINSTALLER — Call must use un.* there; use stock _CHECK_APP_RUNNING.

0 commit comments

Comments
 (0)