EXE process does not end on exit

Ask your PowerShell-related questions, including questions on cmdlet development!
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
This topic is 6 years and 1 month old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked
User avatar
Alexander Riedel
Posts: 8478
Last visit: Tue Mar 26, 2024 8:52 am
Answers: 19
Been upvoted: 37 times

Re: EXE process does not end on exit

Post by Alexander Riedel »

As promised, here is a standard windows forms app packaged as a 64 bit V5 exe.
Run it on your machine, close the form and see if the process exits.
There is no special code to make it exit the process as you can see in the included .psf and .psbuild files.
Attachments
processtest.zip
(135.75 KiB) Downloaded 177 times
Alexander Riedel
SAPIEN Technologies, Inc.
User avatar
PXL_Posh
Posts: 40
Last visit: Thu Nov 07, 2019 5:43 am

Re: EXE process does not end on exit

Post by PXL_Posh »

Thank you for processtest. It worked as advertised. Tested on Win7 x64 and Win10.

I'm unfamiliar with the config and manifest. Would these be necessary when distributing the exe?
I built the EXE again using a default embedded manifest and a config.
Same results.

During execution of the EXE I can see the java runspaces kick off, each perform its duty, generate a log and close during the life cycle of each runspace.

I left out the GUI. The scriptblock is stripped down. The rest is verbatim.

  1. #region Synchronized Collections
  2. $runspace = [hashtable]::Synchronized(@{})
  3. $syncHash = [hashtable]::Synchronized(@{})
  4. $jobCleanup = [hashtable]::Synchronized(@{})
  5. $jobs = [collections.arraylist]::Synchronized([collections.arraylist]@())
  6. $collection = [hashtable]::Synchronized(@{})
  7. #endregion Synchronized Collections
  8.  
  9. #region Extra things for Sync'ed Collections
  10. $collection.ObservableCollection = New-Object System.Collections.ObjectModel.ObservableCollection[object]
  11. $jobCleanup.Flag = $True
  12. #endregion Extra things for Sync'ed Collections
  13.  
  14. #region UI Runspace Creation
  15. $runspace.Runspace =[runspacefactory]::CreateRunspace()
  16. $runspace.Runspace.ApartmentState = "STA"        
  17. $runspace.Runspace.Open()        
  18. $runspace.Runspace.SessionStateProxy.SetVariable("runspace",$runspace)    
  19. $runspace.Runspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
  20. $runspace.Runspace.SessionStateProxy.SetVariable("jobCleanup",$jobCleanup)    
  21. $runspace.Runspace.SessionStateProxy.SetVariable("jobs",$jobs)
  22. $runspace.Runspace.SessionStateProxy.SetVariable("collection",$collection)
  23.  
  24. $runspace.PowerShell = [powershell]::Create().AddScript({
  25.     $syncHash.Error = $Error
  26.    
  27.     #GUI Section
  28.    
  29.     #region Background runspace to clean up jobs
  30.     $newRunspace =[runspacefactory]::CreateRunspace()
  31.     $newRunspace.ApartmentState = "STA"        
  32.     $newRunspace.Open()        
  33.     $newRunspace.SessionStateProxy.SetVariable("jobCleanup",$jobCleanup)    
  34.     $newRunspace.SessionStateProxy.SetVariable("jobs",$jobs)
  35.     $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
  36.     $jobCleanup.PowerShell = [powershell]::Create().AddScript({
  37.         #Routine to handle completed runspaces
  38.         Do {    
  39.             [System.Threading.Monitor]::Enter($Jobs.syncroot)
  40.             Foreach($runspace in $jobs)
  41.             {
  42.                 If ($runspace.Handle.isCompleted)
  43.                 {
  44.                     $null = $runspace.powershell.EndInvoke($runspace.Handle)
  45.                     $runspace.powershell.dispose()
  46.                     $null = $runspace.Handle
  47.                     $null = $runspace.powershell
  48.                 }
  49.             }
  50.             #Clean out unused runspace jobs
  51.             $temphash = $jobs.clone()
  52.             $temphash | Where {
  53.                 $_.runspace -eq $Null
  54.             } | ForEach {
  55.                 $jobs.remove($_)
  56.                 }        
  57.             [System.Threading.Monitor]::Exit($Jobs.syncroot)
  58.             Start-Sleep -Seconds 1    
  59.         } while ($jobCleanup.Flag)
  60.     })
  61.  
  62.     $jobCleanup.PowerShell.Runspace = $newRunspace
  63.     $jobCleanup.Thread = $jobCleanup.PowerShell.BeginInvoke()  
  64.     #endregion
  65.  
  66.     $syncHash.Verify.Add_Click({
  67.  
  68.         $ps = [powershell]::Create().AddScript({
  69.            
  70.             Param ($Collection, $syncHash, $jobs, $Data )
  71.  
  72.             $RunspacePool = [runspacefactory]::CreateRunspacePool(1,5)
  73.             $ScriptBlock{
  74.                 Param()
  75.                 Java.exe -jar C:\Verify\Verify.jar $Row arg2
  76.             }
  77.             Foreach ($Row in $Rows)
  78.             {
  79.                 $ps = [powershell]::Create()
  80.                 $ps.RunspacePool = $RunspacePool
  81.                 $RunspacePool.Open()  
  82.                 $null = $ps.AddScript($ScriptBlock).AddArgument($Row).AddArgument($syncHash)
  83.                 $null = $jobs.Add([pscustomobject]@{
  84.                 PowerShell = $Ps
  85.                 Handle = $PS.BeginInvoke()
  86.                 })
  87.             }
  88.         }).AddArgument($Collection).AddArgument($syncHash).AddArgument($jobs).AddArgument($Row)
  89.  
  90.         [System.Threading.Monitor]::Enter($Jobs.syncroot)
  91.         $jobs.Add([pscustomobject]@{
  92.             PowerShell = $ps
  93.             Handle = $Ps.BeginInvoke()
  94.         })
  95.         [System.Threading.Monitor]::Exit($Jobs.syncroot)
  96.     })
  97.  
  98.     $syncHash.Window.Add_Closed({
  99.         #Halt job processing
  100.         $jobCleanup.Flag = $False
  101.  
  102.         #Stop all runspaces
  103.         $jobCleanup.PowerShell.Dispose()
  104.    
  105.         $runspace.PowerShell.Runspace.Close()
  106.         $runspace.PowerShell.Dispose()
  107.  
  108.         [gc]::Collect()
  109.     [gc]::WaitForPendingFinalizers()
  110.     [System.Windows.Forms.Application]::Exit();Stop-Process -Name "CustomApp" -Force
  111.     })
  112.     #endregion UI Events
  113.  
  114.     $syncHash.Window.ShowDialog()
  115. })
  116. $runspace.PowerShell.Runspace = $runspace.Runspace
  117. $runspace.Handle = $runspace.PowerShell.BeginInvoke()
  118. #endregion UI Runspace Creation
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: EXE process does not end on exit

Post by jvierra »

Please post your file as an attachment. It needs to be the complete PS1 file you are running as you run it and it must cause the issue.

Note how Alex posted his ZIP file.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: EXE process does not end on exit

Post by jvierra »

The code you posted has syntax errors. The code must be posted as a file and must be runnable as it is posted.

A quick look tells me that you are likely deadlocking on a synchash. Without some clear runnable code there is no real way to sort through some hundreds of lines to see hat you are doing.

I will also recommend converting your code to use a workflow which is a controlled and PowerShell compatible way to use multiple runspaces/threads. It is more efficient, easier to manage and easier to code than runspaces.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: EXE process does not end on exit

Post by jvierra »

Here is a quick example of how a workflow does all of the work you are trying to do:

Code: Select all

Get-RunSpace
workflow Test-Workflow{  
    $Disks = Get-Disk  
    ForEach -Parallel ($Disk in $Disks){  
        # The commands run sequentially on each disk.   
        $Disk.Path     
    }  
} 
Test-Workflow
Get-Runspace
Open a new copy of PS command line version and paste the above code. Look at how the workflow generates reusable runspaces. They are left for reuse. When PowerShell closes it will clean these up without any intervention.

There is no need to use synchashes as PS manages access to variables for you in a safe way. A workflow can be set to control the number of tasks running in parallel and as each finishes the runspace will be used to launch another queued task.
User avatar
PXL_Posh
Posts: 40
Last visit: Thu Nov 07, 2019 5:43 am

Re: EXE process does not end on exit

Post by PXL_Posh »

Is there an inherent issue if I am using WPF instead of winforms?
I have never used winforms, I learned on WPF.

Thank you.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: EXE process does not end on exit

Post by jvierra »

Without an example of the code it is not possible to guess at the cause of your issue.

What tool are you using to build the EXE?
User avatar
PXL_Posh
Posts: 40
Last visit: Thu Nov 07, 2019 5:43 am

Re: EXE process does not end on exit

Post by PXL_Posh »

To build the EXE I am using Powershell Studio 2017.
The primary reason I managed to get a budget for the software was the argument I could convert editable scripts into a locked down exe.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: EXE process does not end on exit

Post by jvierra »

What build settings are you using?

Without an example of the code it is not possible to guess at the cause of your issue.
User avatar
PXL_Posh
Posts: 40
Last visit: Thu Nov 07, 2019 5:43 am

Re: EXE process does not end on exit

Post by PXL_Posh »

Here is a sanitized version of the script with the main elements in place.
This would be enough to launch the script but not do anything, which is fine because I can launch the exe successfully.
I can close the window using the button in the upper right but that's when the process does not end.

Thank you
Verify.zip
(3.21 KiB) Downloaded 127 times
The build settings are on the previous page of this post.
This topic is 6 years and 1 month old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked