MScholtes/Win-PS2EXE

Running EXE as a different user leaves process hanging

Closed this issue · 3 comments

I have a PS script that does some stuff with PoshRSJob, AD cmdlets and Graph API rest calls and then spits out a report file. It works great when converted to EXE however if I run the EXE using shift+right click >run as different user, when the process is done it remains hanging in my task manager and still running. I have to kill it manually. If I run the EXE by simple double click it exist at completion as expected.

I tried with another PS script that isn't so advanced and it does close running under different user. I've placed "exit" all over my PS script but it's not quitting when done.

Side note, I am loading another ps1 in to get some functions but even that file I threw an exit at the end.

Hello Nick85,

this sounds a bit complicated. I think there is an issue with using PoshRSJob in PS2EXE. PoshRSJob starts a powershell runspace pool without closing it. Powershell.exe forcefully closes all runspaces on exit, but PS2EXE is running in a runspace by itself. So it waits for the runspaces to close what never happens, this leads to an infinite wait.

I found no easy way to tell PoshRSJob to close its runspaces, so I see two workarounds:

1. Change the runspaces of PoshRSJob to use its own threads

Search for the file Start-RSJob.ps1 in the module directory of PoshRSJob, if installed for the AllUsers context the path is
"C:\Program Files\WindowsPowerShell\Modules\poshrsjob\1.7.4.4\Public\Start-RSJob.ps1".
Edit the file and insert the line
$RunspacePool.ThreadOptions = "UseNewThread"
in the line before
$RunspacePool.Open()
(line 524 as of version 1.7.4.4)

Since PoshRSJob runspaces use their own threads now they can be distinguished from PS2EXE's runspace and get closed on exit.

If you want the runspaces to close faster at the end replace
$RunspacePool.CleanupInterval = [timespan]::FromMinutes(2)
with something like
$RunspacePool.CleanupInterval = [timespan]::FromSeconds(10)
two lines before the expression mentioned above.

2. Close the runspaces manually on exit of your script

Put the following line on all places of your script where an exit can occur:

Get-Runspace | ?{ $.Id -ne [System.Management.Automation.Runspaces.Runspace]::DefaultRunspace } | ?{ $.RunspaceAvailability -lt 3 } | %{ $.Dispose() }_

This line closes all runspaces that are not "Busy" and obviously not the default runspace (you would crash the script engine then). I would not recommend to do this in regular scripts.

Hope this helps.

Greetings

Markus

Thank you! Option 1 worked by modifying the Start-RSJob.ps1 file. This script I have is something I'm hoping to distribute to an operations team so I'm not sure how feasible it is to tell them to modify the PoshRSJob PS1 file. You mentioned you don't recommend doing option 2 for regular scripts, what did you mean by this? Scripts that don't use RSJob?

Update: I think I figured out what you mean. If I run it as part of a regular script it appears to kill the PS window :)
I commented out the line and put a note for anyone looking at it that if they want to make it an EXE they need to comment out the line. It closes the process properly using that small addition to the script.

Thank you!

Isn't it funny that Powershell.exe close itself when it is missing a runspace? One could use this for a hack.

And yes, I would not use solution 2 on scripts or script blocks that are not started with PoshRSJob, but with PoshRSJob this seems to be a valid solution, you don't need the runspaces anymore anyway.

I hope everything's okay for you now, closing the issue now.

Greetings

Markus