Search code examples
powershellxamlrunspace

Multi-Runspace PowerShell/XAML script crashing on button click


I have a script which uses asynchronous runspaces in order to display a XAML/WPF GUI while processing stuff in the background. When I click the button, it crashes, but only when in a specific state. Let me elaborate.

The script begins with pinging a long list of servers to ensure that they're up. After that, it runs through a few SQL queries, WMI calls, other logic, processes all of the data, and then updates my DataGrid in the other window one row at a time with the information.

The button simply brings up a WinForm confirmation:

#$Global:uihash is my synchronized hashtable.

 $Global:uihash.Button.add_click({if([System.Windows.Forms.MessageBox]::Show `
("Yes or No?", "Question",[System.Windows.Forms.MessageBoxButtons]::OKCancel) -eq "OK")

{Do stuff back in main PS Window}

If I press the button while the script is pinging all of the devices, it works perfectly. If I click the button at any other time during the script, the PS Windows immediately flip to not responding and I have to kill them.

From the application event log:

The program PowerShell_ISE.exe version 10.0.10586.117 stopped interacting with Windows and was closed.

I'm like 95% sure it's because pinging devices is the only part of the script which has absolutely zero interaction with the other window, I just don't know how to fix this, or even work around it.

I'm wondering if anybody has seen or experienced this or something similar before, and how you got around it. Any help would be greatly appreciated. Thanks!


Solution

  • I was never able to completely figure this out, but I did find a good workaround for me. I put the main chunk of my script in a Do-Until loop, and made the button click change a global variable I created. That broke it out of the loop, closed the window, and let all the finishing tasks run without crashing.

    #$Global:uihash is my synchronized hashtable.
    
    #Create synchronized hash table variable
    $Global:uiHash.Add(“End”,$false)
    
     #Create Click Event 
    $Global:uihash.Button.add_click({if([System.Windows.Forms.MessageBox]::Show 
    ("Yes or No?", "Question",[System.Windows.Forms.MessageBoxButtons]::OKCancel) -eq "OK")
    {$Global:uiHash.End = $true}
    
    Do {A whole bunch of stuff}
    Until ($global:uiHash.end -eq $true)
    
    #Close the window
    $Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.Window.close() },"Normal")
    #Then process the rest of the script