-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NSIS install fails on terminal servers with multiple users already running the program #6104
NSIS install fails on terminal servers with multiple users already running the program #6104
Comments
Hmmm, you have multiple users accessing the same machine all using their own per-user installation of the same Electron app? It looks like you can actually use your own nsis macro electron-builder/packages/app-builder-lib/templates/nsis/include/allowOnlyOneInstallerInstance.nsh Lines 30 to 36 in d307c21
|
I don't know much about nsis scripts :(. As a quick and dirty, this in installer.nsh seems to have fixed this issue
I don't know what other issues it will cause. Will this cause any issues? |
I'm not too familiar with nsis scripting either. Just picking it up while I go tbh. I don't foresee that causing any issues, but then again, I also wasn't expecting this use case where multiple users are concurrently using different instances of the app on the same terminal server. |
Well it change made everyone happy again so I guess that worked. Should I leave this issue open because the solution was just bypassing electron-builders nsis script and it should still be fixed? |
I have seen similar problem but with different message on similar setup (terminal service environment). I guess Windows allows non-previleged process seeing image names of processes in other users' sessions, but not seeing image paths (nor killing them). Maybe we should not test if the app is running but test if the app executable is locked (opened), to evaluate the possibility of install/update? |
Should be possible to check if the app is running and what user is running it. Only close the current users versions. Something like this powershell command gives the user ID with the app Get-WmiObject -Class Win32_Process |
Select-Object Name,Path, @{
Name = 'Owner'
Expression = {
$_.GetOwner().User
}
} |
Definitely. But not with |
Had to google it but if this is the plugin electron used https://nsis.sourceforge.io/NsProcess_plugin then it doesn't really work on terminal servers because it finds processes from all users. An example Get-Process | ? {$_.SI -eq (Get-Process -PID $PID).SessionId} | ? {$_.ProcessName -eq "electron"} Change |
I also have this problem with a larger deployment, where the initial installation as well as later updates fail, as long as other instances run on the same terminal server under a different user. |
@Simolation Sort of yeah. As long as in app you still run the quit and update function it still works fine. |
I found now more or less a solution which is better than just skipping everything. What I did is to take the script electron-builder uses normally, and I just removed the message boxes. So, the installer tries closing the application and when it does not work, it just installs it anyway. It is skipped, but it also tries to close it at least. This should prevent problems when the application is actually running. I took this as a base: electron-builder/packages/app-builder-lib/templates/nsis/include/allowOnlyOneInstallerInstance.nsh Lines 39 to 96 in 41a59f9
Here is the modified code of my !include "getProcessInfo.nsh"
Var pid
!macro customCheckAppRunning
${GetProcessInfo} 0 $pid $1 $2 $3 $4
${if} $3 != "${APP_EXECUTABLE_FILENAME}"
${if} ${isUpdated}
# allow app to exit without explicit kill
Sleep 300
${endIf}
${nsProcess::FindProcess} "${APP_EXECUTABLE_FILENAME}" $R0
${if} $R0 == 0
${if} ${isUpdated}
# allow app to exit without explicit kill
Sleep 1000
Goto doStopProcess
${endIf}
# Skip message box
# MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "$(appRunning)" /SD IDOK IDOK doStopProcess
# Quit
doStopProcess:
DetailPrint `Closing running "${PRODUCT_NAME}"...`
# https://github.com/electron-userland/electron-builder/issues/2516#issuecomment-372009092
nsExec::Exec `taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"` $R0
# to ensure that files are not "in-use"
Sleep 300
# Retry counter
StrCpy $R1 0
loop:
IntOp $R1 $R1 + 1
${nsProcess::FindProcess} "${APP_EXECUTABLE_FILENAME}" $R0
${if} $R0 == 0
# wait to give a chance to exit gracefully
Sleep 1000
nsExec::Exec `taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"` $R0
${If} $R0 != 0
DetailPrint `Waiting for "${PRODUCT_NAME}" to close (taskkill exit code $R0).`
Sleep 2000
${endIf}
${else}
Goto not_running
${endIf}
# App likely running with elevated permissions.
# Ask user to close it manually
${if} $R1 > 1
# Just skip the message box and continue installing
Goto not_running
${else}
Goto loop
${endIf}
not_running:
${endIf}
${endIf}
!macroend I haven't tested it on a terminal server yet, this is going to happen on Monday 🤞 |
I tried something similar, but found it did in fact close the process randomly. Roughly half the tests I ran it successfully closed, other times it complained it failed to close it. But that could be an environment problem here. |
So far, everything has worked perfectly. I tried it on two different terminal server configurations, and it worked for ~25 devices without any issues. |
Thinking of #5902, simply skipping dialog seems not the best way, as that would leave elevated process running and fail to install. Elevated instances owned by current user are something current user should close. So I think @TDola's pwsh solution (or maybe Or, maybe just making MessageBox ignorable could be enough? So we leave them to users and forget about machine-wide install, elevated processes, terminal servers, processes owned by other users with Then these lines electron-builder/packages/app-builder-lib/templates/nsis/include/allowOnlyOneInstallerInstance.nsh Line 89 in f5c1e00
should look like: MessageBox MB_ABORTRETRYIGNORE|MB_ICONEXCLAMATION "$(appCannotBeClosed)" /SD IDABORT IDRETRY loop IDIGNORE not_running |
I can't really trust users not to click a button that will shut down the application for everyone else 😞 |
Only check for processes owned by current user when the app is installed per-user. On per-user installation, other users are running their own copy of the app. These instances will not affect install and are safe to ignore. fixes electron-userland#6104
Oh no. I misunderstood the problem. Anyways, both of our situations should be resolved with replacing ${nsProcess::FindProcess} with one checking the owner of process. Can you try replacing |
Um, no, this isn't enough. If current user have the app running, this will kill other users instances too. |
That sounds perfect. I look forward to testing it |
Only find and kill processes owned by current user on install. On per-user installation, other users run their own copy of the app. These instances will not block install and are should be left untouched. fixes electron-userland#6104
Would love to have a PR submitted for this if possible! :) |
Seems not possible yet. The problem is that, taskkill returns 0 even it successfully killed only gpu process (1 of 4 elevated process). I'll try modifying the code again to see tasklist instead and see if that works.,, |
i still have this problem...., the code is right, with the PR code |
22.11.7
Which version of node are you using?
14.17.1
Which version of electron are you using?
8.5.5
Which version of electron-updater are you using (if applicable)?
4.3.9
For which target are you building for?
The issue I am having is the NSIS installer incorrectly determines the application is still running on terminal servers if any user has it open, even when using per user. This blocks the install most of the time, or worse yet, auto kills all instances on the terminal server for all users when one user wants to update their individual install. Both of these are serious bugs. The installer should not check processes for other users when it is installed to one user folder. And it absolutely should not be able to kill the process for other users.
To reproduce. Build an NSIS-web installer.
Connect to a terminal server with 2 different users. Install and run the application one one user. Then try to install on the other, it will fail.
On the right is the application running on a terminal server user. On the left is the installer trying to run on the same server but a different user
Is there a way to disable to is running check with a custom nsis script or anything? We encountered this bug during a large deployment which we have now paused.
The text was updated successfully, but these errors were encountered: