1

因为我的雇主不想使用已编译的软件,所以他们要求我创建一个 GUI,使用 PowerShell 并行 ping 一系列设备。我的 PowerShell 脚本由一个表单和该表单上的一个按钮组成,用于 ping 设备。为了防止 GUI 锁定,我使用运行空间将 ping 卸载到单独的线程。我可以 ping 设备并使用运行空间中的信息更新表单,但是当我完成应用程序时,我无法关闭/处置运行空间,因此即使在应用程序退出后它也会继续运行。

下面提供的函数 ping localhost 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()
}

关闭应用程序时出现的错误是

Ping 设备
AsyncHandle 为 Null = True
您不能在空值表达式上调用方法。
在 C:\Users\Loligans\Drive\dboardscript.ps1:673 char:5
+ $data = $powershell.EndInvoke($AsyncHandle)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

您不能在空值表达式上调用方法。
在 C:\Users\Loligans\Drive\dboardscript.ps1:674 char:5
+ $powershell.Dispose()
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

您不能在空值表达式上调用方法。
在 C:\Users\Loligans\Drive\dboardscript.ps1:675 char:5
+ $运行空间。关闭()
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

我认为这个问题正在发生,因为运行空间正在执行,但它在它没有运行时也会发生。但是,当它全部耦合在这样的同一个函数中时,它会成功关闭且没有错误

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()
}

我怎样才能让运行空间在它所在的同一个函数之外释放它的所有资源?

4

1 回答 1

1

$powershell很可能不是全局变量,因此您有 2 个不同的变量$powershell,一个在函数的上下文中填充PingDevices(),另一个(空)在函数的上下文中CleanupResources()使用范围修饰符更改变量的范围以避免这种情况:($script:powershell$global:powershell)。

于 2016-02-29T02:18:41.347 回答