0

因为我的雇主不想使用已编译的软件,他们要求我创建一个使用PowerShell并行处理一系列设备的GUI。我的PowerShell脚本包含一个窗体和一个按钮,该窗体用于对设备进行ping操作。为了防止GUI被锁定,我使用Runspace将ping分流到一个单独的线程。我能够ping通设备并使用来自Runspace的信息更新表单,但是当我完成应用程序时,我无法关闭/处理Runspace,因此即使在应用程序退出后它也会继续运行。为什么我无法处理运行空间?

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

关闭应用程序时,我得到的错误是

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

我以为是因为运行空间在执行问题发生了什么,但是当它不运行,以及它发生。然而,它没有误差地成功关闭,当这一切被连接在同一个函数内这样

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

我怎样才能运行空间来释放它驻留在同一功能之外的所有资源?

+0

通过在同一个类中使用'System.Net.NetworkInformation.SendAsync'和'PingCompleted'事件,您可以完全摆脱替代运行空间。 –

回答

1

$powershell最有可能不是一个全局变量,所以你有2个不同的变量$powershell,指的是它在功能PingDevices()的背景填充,另一个(空)一个在功能CleanupResources()的情况下。使用scope modifier更改变量的范围以避免出现这种情况:$script:powershell(或$global:powershell)。

+0

这工作!非常感谢你。你能否更深入地解释为什么在其他函数中我可以定义一个变量(例如$ one = 1)并从其他函数中调用它,但是当涉及到Runspaces时,我无法从没有$的另一个函数调用它的引用Global引用了引用名称? – Loligans

+0

@Loligans应该没有区别。如果它在别处工作,那么在函数环境中使用它之前,很可能已经有了一个具有该名称的全局变量。 –

+0

我会研究它,但将变量设置为全局解决了问题。再次感谢! – Loligans

相关问题