I'm currently working on a WPF GUI using PowerShell v5, and I have a button that triggers a script to run in a Runspace. My issue is that I don't know how to appropriately close the Runspace once the script has finished executing. I've attempted to include .Close() and .Dispose() at the end of the button's click event, but that hasn't worked. Here's the relevant part of my Add_Click event:
```powershell
search.add_Click({
# Create and Open Runspace
$runspace = [runspacefactory]::CreateRunspace()
$runspace.ApartmentState = "STA"
$runspace.Open()
$runspace.SessionStateProxy.SetVariable("syncHash", $syncHash)
# Execute Script
$powershell = [powershell]::Create().AddScript($backgroundScript)
$powershell.Runspace = $runspace
$powershell.BeginInvoke()
# Close / Dispose attempts (not working)
#$runspace.close()
#$runspace.Dispose()
#$powershell.Dispose()
})
```
2 Answers
You can actually close the Runspace when the WPF window is closing. Here’s a quick outline on how to update your click event for the search:
1. Use global variables for the Runspace and PowerShell job.
2. Set up your WPF window to manage the closing event.
Here’s a sample implementation:
```powershell
$global:runspace = [runspacefactory]::CreateRunspace()
$global:powershell = [powershell]::Create().AddScript($backgroundScript)
$global:job = $global:powershell.BeginInvoke()
$Window.add_Closing({
if (($null -ne $global:powershell) -and (-not $global:job.IsCompleted)) {
[Windows.MessageBox]::Show("Still running.")
$PSItem.Cancel = $true
}
})
$Window.add_Closed({
if ($null -ne $global:powershell) {
$global:powershell.EndInvoke($global:job)
}
$global:runspace.Close()
})
```
A good approach is to keep track of your job status using a synchronization hash table. When the job is set up, store its status. Then, in a while loop, you can actively check for updates on that status and close the Runspace accordingly.
There are plenty of examples out there. Just make sure that your while loop isn’t running in the button click event, but perhaps after your GUI initializes. This way, it can constantly monitor the job status without blocking the GUI.

Hi! I get what you're saying about the synchronization hash table. But I’m confused about the best place to implement this. Should I just leave the while loop running once the GUI is loaded?