@@ -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
142142hspWaitPackagedDone:
143+ ; Let handles on DLLs under $INSTDIR release (Program Files upgrades).
144+ Sleep 400
143145FunctionEnd
144146
145147Function 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
174181FunctionEnd
175182
176183Function 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