为什么我无法处理运行空间?
Why am I unable to Dispose of Runspace?
因为我的雇主不想使用编译软件,他们要求我创建一个 GUI,使用 PowerShell 并行 ping 一系列设备。我的 PowerShell 脚本由一个表单和一个用于对设备执行 ping 操作的按钮组成。为了防止 GUI 锁定,我使用运行空间将 ping 卸载到一个单独的线程。我能够 ping 设备并使用来自运行空间的信息更新表单,但是当我完成应用程序时,我无法 close/Dispose 运行空间,因此即使在应用程序退出后它仍保持 运行 .
下面提供的函数 ping 本地主机 10 次并将结果添加到 GUI 中的 ListView。
Function PingDevices
{
Write-Host "Pinging Devices"
$items = $StorePingInfo_ListView.Items
$ScriptBlock =
{
$a = 0
for(;$a -lt 10; $a++)
{
$PingResult = Test-Connection 127.0.0.1 -Count 1
#[System.Windows.Forms.MessageBox]::Show($PingResult)
$items.Add("Name").SubItems.Add($PingResult)
sleep 1
}
}
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Items',$items)
$powershell = [System.Management.Automation.PowerShell]::create()
$powershell.Runspace = $runspace
$powershell.AddScript($ScriptBlock)
$AsyncHandle = $powershell.BeginInvoke()
}
Function CleanupResources
{
#When I try to clean up the resources I get Null errors
Write-Host "AsyncHandle is Null = "($AsyncHandle -eq $null)
$data = $powershell.EndInvoke($AsyncHandle)
$powershell.Dispose()
$runspace.Close()
}
我在关闭应用程序时遇到的错误是
Pinging Devices
AsyncHandle is Null = True
You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:673 char:5
+ $data = $powershell.EndInvoke($AsyncHandle)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:674 char:5
+ $powershell.Dispose()
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\Loligans\Drive\dboardscript.ps1:675 char:5
+ $runspace.Close()
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
我认为问题的发生是因为 Runspace 正在执行,但当它不是 运行 时也会发生。然而,当它像这样在同一个函数中耦合时,它会成功关闭而没有错误
Function PingDevices
{
Write-Host "Pinging Devices"
$items = $StorePingInfo_ListView.Items
$ScriptBlock =
{
$a = 0
for(;$a -lt 10; $a++)
{
$PingResult = Test-Connection 127.0.0.1 -Count 1
#[System.Windows.Forms.MessageBox]::Show($PingResult)
$items.Add("Name").SubItems.Add($PingResult)
sleep 1
}
}
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Items',$items)
$powershell = [System.Management.Automation.PowerShell]::create()
$powershell.Runspace = $runspace
$powershell.AddScript($ScriptBlock)
$AsyncHandle = $powershell.BeginInvoke()
$data = $powershell.EndInvoke($AsyncHandle)
$powershell.Dispose()
$runspace.Close()
}
如何让 Runspace 释放它所在的同一函数之外的所有资源?
$powershell
很可能不是全局变量,因此您有 2 个不同的变量 $powershell
,一个在函数 PingDevices()
的上下文中填充,另一个 (空)一个在函数上下文中 CleanupResources()
。使用 scope modifier 更改变量的范围以避免这种情况:$script:powershell
(或 $global:powershell
)。
因为我的雇主不想使用编译软件,他们要求我创建一个 GUI,使用 PowerShell 并行 ping 一系列设备。我的 PowerShell 脚本由一个表单和一个用于对设备执行 ping 操作的按钮组成。为了防止 GUI 锁定,我使用运行空间将 ping 卸载到一个单独的线程。我能够 ping 设备并使用来自运行空间的信息更新表单,但是当我完成应用程序时,我无法 close/Dispose 运行空间,因此即使在应用程序退出后它仍保持 运行 .
下面提供的函数 ping 本地主机 10 次并将结果添加到 GUI 中的 ListView。
Function PingDevices
{
Write-Host "Pinging Devices"
$items = $StorePingInfo_ListView.Items
$ScriptBlock =
{
$a = 0
for(;$a -lt 10; $a++)
{
$PingResult = Test-Connection 127.0.0.1 -Count 1
#[System.Windows.Forms.MessageBox]::Show($PingResult)
$items.Add("Name").SubItems.Add($PingResult)
sleep 1
}
}
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Items',$items)
$powershell = [System.Management.Automation.PowerShell]::create()
$powershell.Runspace = $runspace
$powershell.AddScript($ScriptBlock)
$AsyncHandle = $powershell.BeginInvoke()
}
Function CleanupResources
{
#When I try to clean up the resources I get Null errors
Write-Host "AsyncHandle is Null = "($AsyncHandle -eq $null)
$data = $powershell.EndInvoke($AsyncHandle)
$powershell.Dispose()
$runspace.Close()
}
我在关闭应用程序时遇到的错误是
Pinging Devices AsyncHandle is Null = True You cannot call a method on a null-valued expression. At C:\Users\Loligans\Drive\dboardscript.ps1:673 char:5 + $data = $powershell.EndInvoke($AsyncHandle) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull You cannot call a method on a null-valued expression. At C:\Users\Loligans\Drive\dboardscript.ps1:674 char:5 + $powershell.Dispose() + ~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull You cannot call a method on a null-valued expression. At C:\Users\Loligans\Drive\dboardscript.ps1:675 char:5 + $runspace.Close() + ~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
我认为问题的发生是因为 Runspace 正在执行,但当它不是 运行 时也会发生。然而,当它像这样在同一个函数中耦合时,它会成功关闭而没有错误
Function PingDevices
{
Write-Host "Pinging Devices"
$items = $StorePingInfo_ListView.Items
$ScriptBlock =
{
$a = 0
for(;$a -lt 10; $a++)
{
$PingResult = Test-Connection 127.0.0.1 -Count 1
#[System.Windows.Forms.MessageBox]::Show($PingResult)
$items.Add("Name").SubItems.Add($PingResult)
sleep 1
}
}
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Items',$items)
$powershell = [System.Management.Automation.PowerShell]::create()
$powershell.Runspace = $runspace
$powershell.AddScript($ScriptBlock)
$AsyncHandle = $powershell.BeginInvoke()
$data = $powershell.EndInvoke($AsyncHandle)
$powershell.Dispose()
$runspace.Close()
}
如何让 Runspace 释放它所在的同一函数之外的所有资源?
$powershell
很可能不是全局变量,因此您有 2 个不同的变量 $powershell
,一个在函数 PingDevices()
的上下文中填充,另一个 (空)一个在函数上下文中 CleanupResources()
。使用 scope modifier 更改变量的范围以避免这种情况:$script:powershell
(或 $global:powershell
)。