Skip to content

Commit c9480bc

Browse files
authored
feat(nsis): terminate only processes running in installation folder (electron-userland#9069)
1 parent 35f5f6e commit c9480bc

File tree

2 files changed

+75
-24
lines changed

2 files changed

+75
-24
lines changed

.changeset/flat-trees-return.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"app-builder-lib": patch
3+
---
4+
5+
feat(nsis): terminate only processes running in installation folder

packages/app-builder-lib/templates/nsis/include/allowOnlyOneInstallerInstance.nsh

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,77 @@
3030
!macroend
3131

3232
!macro CHECK_APP_RUNNING
33-
!ifmacrodef customCheckAppRunning
34-
!insertmacro customCheckAppRunning
33+
Var /GLOBAL CmdPath
34+
Var /GLOBAL FindPath
35+
Var /GLOBAL PowerShellPath
36+
!ifmacrodef customCheckAppRunning
37+
!insertmacro customCheckAppRunning
38+
!else
39+
StrCpy $CmdPath "$SYSDIR\cmd.exe"
40+
StrCpy $FindPath "$SYSDIR\find.exe"
41+
StrCpy $PowerShellPath "$SYSDIR\WindowsPowerShell\v1.0\powershell.exe"
42+
!insertmacro IS_POWERSHELL_AVAILABLE
43+
!insertmacro _CHECK_APP_RUNNING
44+
!endif
45+
!macroend
46+
47+
!macro IS_POWERSHELL_AVAILABLE
48+
Var /GLOBAL IsPowerShellAvailable ; 0 = available, 1 = not available
49+
# Try running PowerShell with a simple command to check if it's available
50+
nsExec::Exec `"$PowerShellPath" -C "if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"`
51+
Pop $0 # Return code (0 = success, other = error)
52+
53+
${if} $0 == 0
54+
# PowerShell is available, check if it's not blocked by policies
55+
nsExec::Exec `"$PowerShellPath" -C "if ((Get-ExecutionPolicy -Scope Process) -eq 'Restricted') { exit 1 } else { exit 0 }"`
56+
Pop $0
57+
${endIf}
58+
59+
${if} $0 != 0
60+
StrCpy $0 1
61+
${endIf}
62+
63+
StrCpy $IsPowerShellAvailable $0
64+
!macroend
65+
66+
!macro FIND_PROCESS _FILE _RETURN
67+
${if} $IsPowerShellAvailable == 0
68+
nsExec::Exec `"$PowerShellPath" -C "if ((Get-CimInstance -ClassName Win32_Process | ? {$$_.Path -and $$_.Path.StartsWith('$INSTDIR', 'CurrentCultureIgnoreCase')}).Count -gt 0) { exit 0 } else { exit 1 }"`
69+
Pop ${_RETURN}
70+
${else}
71+
!ifdef INSTALL_MODE_PER_ALL_USERS
72+
${nsProcess::FindProcess} "${_FILE}" ${_RETURN}
3573
!else
36-
!insertmacro _CHECK_APP_RUNNING
74+
# find process owned by current user
75+
nsExec::Exec `"$CmdPath" /C tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" /FO CSV | "$FindPath" "${_FILE}"`
76+
Pop ${_RETURN}
3777
!endif
78+
${endIf}
3879
!macroend
3980

40-
!macro FIND_PROCESS _FILE _ERR
41-
!ifdef INSTALL_MODE_PER_ALL_USERS
42-
${nsProcess::FindProcess} "${_FILE}" ${_ERR}
43-
!else
44-
# find process owned by current user
45-
nsExec::Exec `"$SYSDIR\cmd.exe" /c tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" /FO csv | "$SYSDIR\find.exe" "${_FILE}"`
46-
Pop ${_ERR}
47-
!endif
48-
!macroend
81+
!macro KILL_PROCESS _FILE _FORCE
82+
Push $0
83+
${if} ${_FORCE} == 1
84+
${if} $IsPowerShellAvailable == 0
85+
StrCpy $0 "-Force"
86+
${else}
87+
StrCpy $0 "/F"
88+
${endIf}
89+
${else}
90+
StrCpy $0 ""
91+
${endIf}
92+
93+
${if} $IsPowerShellAvailable == 0
94+
nsExec::Exec `"$PowerShellPath" -C "Get-CimInstance -ClassName Win32_Process | ? {$$_.Path -and $$_.Path.StartsWith('$INSTDIR', 'CurrentCultureIgnoreCase')} | % { Stop-Process -Id $$_.ProcessId $0 }"`
95+
${else}
96+
!ifdef INSTALL_MODE_PER_ALL_USERS
97+
nsExec::Exec `taskkill /IM "${_FILE}" /FI "PID ne $pid"`
98+
!else
99+
nsExec::Exec `"$CmdPath" /C taskkill $0 /IM "${_FILE}" /FI "PID ne $pid" /FI "USERNAME eq %USERNAME%"`
100+
!endif
101+
${endIf}
102+
Pop $0
103+
!macroend
49104

50105
!macro _CHECK_APP_RUNNING
51106
${GetProcessInfo} 0 $pid $1 $2 $3 $4
@@ -69,12 +124,7 @@
69124

70125
DetailPrint "$(appClosing)"
71126

72-
# https://github.com/electron-userland/electron-builder/issues/2516#issuecomment-372009092
73-
!ifdef INSTALL_MODE_PER_ALL_USERS
74-
nsExec::Exec `taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
75-
!else
76-
nsExec::Exec `"$SYSDIR\cmd.exe" /c taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
77-
!endif
127+
!insertmacro KILL_PROCESS "${APP_EXECUTABLE_FILENAME}" 0
78128
# to ensure that files are not "in-use"
79129
Sleep 300
80130

@@ -88,13 +138,9 @@
88138
${if} $R0 == 0
89139
# wait to give a chance to exit gracefully
90140
Sleep 1000
91-
!ifdef INSTALL_MODE_PER_ALL_USERS
92-
nsExec::Exec `taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
93-
!else
94-
nsExec::Exec `"$SYSDIR\cmd.exe" /c taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
95-
!endif
141+
!insertmacro KILL_PROCESS "${APP_EXECUTABLE_FILENAME}" 1 # 1 = force kill
96142
!insertmacro FIND_PROCESS "${APP_EXECUTABLE_FILENAME}" $R0
97-
${If} $R0 == 0
143+
${if} $R0 == 0
98144
DetailPrint `Waiting for "${PRODUCT_NAME}" to close.`
99145
Sleep 2000
100146
${else}

0 commit comments

Comments
 (0)