You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell会话挂起:如何正确释放表单、关闭Runspace及会话?

问题解答:PowerShell等待GIF窗口与Runspace资源释放的正确实现

原代码阻塞原因

原代码执行到$Powershell.EndInvoke($Handle)时卡住,核心问题有两个:

  1. Runspace脚本中调用ShowDialog()会阻塞Runspace线程,必须等窗口关闭才会继续执行。但主线程先调用$Gif_Form.One.Dispose()强制释放窗口资源,导致Runspace的ShowDialog()处于异常状态,EndInvoke()无法正常完成。
  2. Runspace脚本内重复创建$Gif_Form.One对象,覆盖了主线程初始化的实例,同步哈希表的跨线程共享逻辑被破坏。

改写代码的可行性

改写后的代码完全可以采用,它精准解决了原代码的问题,同时优化了逻辑:

  • 将表单和PictureBox的创建、GIF加载移到主线程完成,避免跨线程重复创建对象,减少资源冗余和同步问题。
  • 主线程完成Get-ChildItem后,先调用$Gif_Form.One.Close()主动关闭窗口,让Runspace中的ShowDialog()退出阻塞,此时$Powershell.EndInvoke($Handle)能正常执行,不会卡住。
  • 把异步加载LoadAsync()改为同步Load(),因为GIF在主线程提前加载完成,避免Runspace中异步加载可能的资源同步问题。

原代码

Add-Type -AssemblyName System.Windows.Forms 
Add-Type -AssemblyName System.Drawing    
Clear-Host
$Gif_Form = [hashtable]::Synchronized(@{})
$Gif_Form.One = New-Object system.Windows.Forms.Form
$Runspace = [Runspacefactory]::CreateRunspace()
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable('Gif_Form',$Gif_Form)
$Powershell = [Powershell]::Create()
$Powershell.Runspace = $Runspace
$Powershell.AddScript(
{ 
 Add-Type -AssemblyName System.Windows.Forms 
 Add-Type -AssemblyName System.Drawing       

 $Gif_Form.One = New-Object system.Windows.Forms.Form
 $Gif_Form.One.Text = "PLEASE WAIT..."
 $Gif_Form.One.Location = New-Object System.Drawing.Size(1200,100)
 $Gif_Form.One.StartPosition = "Manual"
 $Gif_Form.One.Size = New-Object System.Drawing.Size(166,160)
 $Gif_Form.One.AutoSizeMode = "GrowAndShrink"
 $Gif_Form.One.BackColor = "RED"
 $Gif_Form.One.ControlBox = $FALSE
 $Gif_Form.One.Enabled = $TRUE
 $Gif_Form.One.Add_Shown({$Gif_FORM.Activate()})

 $PictureBox = New-Object Windows.Forms.PictureBox
 $PictureBox.LoadAsync("G:\Dog Chasing Tail.gif")
 $PictureBox.BackColor = "RED"
 $PictureBox.SizeMode = "AutoSize"
 $Picturebox.Visible = $TRUE
 $X = 25
 $Y = 10
 $Picturebox.Location = New-Object System.Drawing.Size($X,$Y)
 $Gif_Form.One.controls.add($PictureBox)
 
 $Gif_Form.One.Visible=$FALSE
 $Gif_Form.One.ShowDialog()
})
$Handle = $Powershell.BeginInvoke() 
Write-Host "Starting GET-ChildItem command..."
$Folders = $Null
#---------------------------------------------------------#
$Folders = Get-Childitem -Path C:\  `
                         -Directory `
                         -Recurse   `
                         -ErrorAction SilentlyContinue
#---------------------------------------------------------#
# Test the automatic variable $? to see if the previous   #
# Command has completed successfully.  If $? is equal to  #
# $TRUE, then the command completed successfully.         #
#---------------------------------------------------------#
Write-Host "...Get-ChildItem is done."
#---------------------------------------------------------#
# Get rid of the Powershell session and runspace          #
# value was computed.                                     #
#---------------------------------------------------------#
$Gif_Form.One.Dispose()
$Powershell.EndInvoke($Handle)
Write-Host "Did I get this far?"
$RunSpace.Close()
$Powershell.Dispose()
Foreach ($PSItem in $Folders) 
{
 Write-Host $PsItem.Name -BackgroundColor Black `
                         -ForegroundColor Green
}

改写后的代码

Add-Type -AssemblyName System.Windows.Forms 
Add-Type -AssemblyName System.Drawing  
Clear-Host
$Gif_Form = [hashtable]::Synchronized(@{})
$Gif_Form.One = New-Object system.Windows.Forms.Form
$Gif_Form.One.Text = "PLEASE WAIT..."
$Gif_Form.One.Location = New-Object System.Drawing.Size(1200,100)
$Gif_Form.One.StartPosition = "Manual"
$Gif_Form.One.Size = New-Object System.Drawing.Size(166,160)
$Gif_Form.One.AutoSizeMode = "GrowAndShrink"
$Gif_Form.One.BackColor = "RED"
$Gif_Form.One.ControlBox = $FALSE
$Gif_Form.One.Enabled = $TRUE

$PictureBox = New-Object Windows.Forms.PictureBox
$PictureBox.Load("G:\MyFunctions\Dog Chasing Tail.gif")
$PictureBox.BackColor = "RED"
$PictureBox.SizeMode = "AutoSize"
$Picturebox.Visible = $TRUE
$Picturebox.Location = New-Object System.Drawing.Size(25,10)
$Gif_Form.One.Controls.add($PictureBox)

$Runspace = [Runspacefactory]::CreateRunspace()
$Runspace.Open()
$Runspace.SessionStateProxy.SetVariable('Gif_Form',$Gif_Form)
$Powershell = [Powershell]::Create()
$Powershell.Runspace = $Runspace
$Powershell.AddScript(
{ 
 $Gif_Form.One.Visible=$FALSE
 $Gif_Form.One.Showdialog()
})
$Handle = $Powershell.BeginInvoke()

$Folders = $Null
#---------------------------------------------------------#
Write-Host "Starting GET-ChildItem command..."
$Folders = Get-Childitem -Path C:\  `
                         -Directory `
                         -Recurse   `
                         -ErrorAction SilentlyContinue
Write-Host "...Get-ChildItem is done."
#---------------------------------------------------------#
# Get rid of the Powershell session and runspace          #
# value was computed.                                     #
#---------------------------------------------------------#
$Gif_Form.One.Close()
$Gif_Form.One.Dispose()
$Powershell.EndInvoke($Handle)
$RunSpace.Close()
$Powershell.Dispose()
Foreach ($PSItem in $Folders) 
{
 Write-Host $PsItem.Name -BackgroundColor Black `
                         -ForegroundColor Green
}

内容的提问来源于stack exchange,提问作者Fr. Eugene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 07:45:57