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

相關問題