I’m troubleshooting the logic of a script that does some long BG operation. I need user to be able to abort it in GUI. Here’s a simplified version, the script sleeps 3 sec in a runspace, then returns “OK” that is picked up by a Winform timer event. If user aborts it by pressing ‘Stop’ button which calls $Powershell.Stop() method it works fine, but if hes then re-initiates the job - $AsyncResult returns nothing. If you press ‘Do’ button one more time - it gets back to normal.
That’s how it works on PS 5.0. I’ve checked it on 2.0 - it works as expected there, it returns result every time, no matter if previous job finished normally or was forced quited. What am I missing here?
Add-Type -AssemblyName System.Windows.Forms $form = New-Object 'System.Windows.Forms.Form' $buttonDo = New-Object 'System.Windows.Forms.Button' $buttonStop = New-Object 'System.Windows.Forms.Button' $timer = New-Object 'System.Windows.Forms.Timer' $BGScriptBlock = { $synchash.form.Text = "Job is being done..." start-sleep 3 return "OK" } $synchash = [Hashtable]::Synchronized(@{ }) $script:Powershell = [PowerShell]::Create().AddScript($BGScriptBlock).AddArgument($PC) $sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() $runspace = [RunspaceFactory]::CreateRunspace($sessionstate) $runspace.ApartmentState = "STA" $runspace.ThreadOptions = "ReuseThread" $runspace.Open() $runspace.SessionStateProxy.SetVariable("synchash", $synchash) $Powershell.Runspace = $runspace $buttonDo_Click = { $script:AsyncResult = $Powershell.BeginInvoke() $timer.Enabled = $true; $timer.Start(); $script:tick = 0 } $buttonStop_Click = { $Powershell.Stop() $form.Text = 'Stopped' } $TimerTick = { $script:tick++; write-host $script:tick; switch ($script:Powershell.InvocationStateInfo.State) { 'Stopped'{write-host "Stopped" } 'Completed' { $result = $Powershell.EndInvoke($script:AsyncResult); write-host "Completed, result: $result"} {$_ -match "Stop|Completed"} {$timer.Stop(); $timer.Enabled = $false; $form.Text = 'Done'} } } $form.Controls.Add($buttonDo) $form.Controls.Add($buttonStop) $form.Size = '400, 150' $form.Text = 'Form' $form.Topmost = $true $buttonDo.Location = '73, 37' $buttonDo.Size = '100, 30' $buttonDo.Text = 'Do' $buttonDo.add_Click($buttonDo_Click) $buttonStop.Location = '209, 37' $buttonStop.Size = '100, 30' $buttonStop.Text = 'Stop' $buttonStop.add_Click($buttonStop_Click) $timer.Interval = 1000 $timer.add_Tick($TimerTick) $synchash.form = $form $form.ShowDialog()
Well, in real world I’m trying to initiate a PSRemoting session over HHTPS/SSL, the strange thing about is that if the session is initiated against a server that is not set up for HTTPS/SSL it waits a good minute before the time-out occures. In PS 5.0 I can force quit it using $Powershell.Close() or $Powershell.Dispose() or even $runspace.Close() but in 2.0 any of these doesn’t kill the thread, it stumbles upon a non-respoding command and freezes until it finishes. These methods are executed but only a minute later. Is there something that can be done about it?