2015-10-27 77 views
2

我正在嘗試拖動的腳本有點不知所措。Powershell運行空間將不會執行

簡而言之:我想掃描我的域計算機的WinRM連接 - 我可以做到這一點很好。問題是,它需要5分鐘才能完成 - 這就是爲什麼我想要多線程的任務。

工作的非多線程代碼:

# this is normaly a textfile with lots of machine hostnames 
$computers = "PC100","PC106","PC124","PC115","PC21" 

function checkMachine($computers){ 

    $ErrorActionPreference = "Stop" 

    foreach ($item in $computers){ 
    #the function contest only performs a ping and returne $true or $false 
    $connection = ConTest($item) 
    if($connection){ 
     try{ 
     $winRM = test-wsman -ComputerName $item 
     if($winRM){ 
      write-host "winRM" 
      [void] $objListboxLeft.Items.Add($item) 
     } 
     }catch{ 
     write-host "NO winRM" 
     [void] $objListboxCenter.Items.Add($item) 
     } 
    }else{ 
     write-host "offline" 
     [void] $objListboxRight.Items.Add($item) 
    } 
    } 
} 

這基本上是什麼我不skript /會做只是一小部分,但它是需要年齡的一部分。

我失敗的運行空間測試 - 我基本上沒有得到任何結果。沒有文本框,我的命令行沒有輸出,我基本上不知道我做錯了什麼。

多線程代碼:

function MulticheckMachine($computers){ 

    $ErrorActionPreference = "Stop" 

    $runspaceCollection = @() 
    $runspacePool = [RunspaceFactory]::CreateRunspacePool(1,5) 
    $runspacePool.open() 

    $scriptBlock = { 
    Param($item) 

     $connection = ConTest($item) 
     if($connection){ 
     try{ 
      test-wsman -ComputerName $item 
      $winRM = test-wsman -ComputerName $item 
      if($winRM){ 
      write-host "winRM" 
      [void] $objListboxLeft.Items.Add($item) 
      } 
     }catch{ 
      write-host "NO winRM" 
      [void] $objListboxCenter.Items.Add($item) 
     } 
     }else{ 
     write-host "offline" 
     [void] $objListboxRight.Items.Add($item) 
     } 
    } 

    Foreach($item in $computers){ 
    $powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item) 
    $powershell.runspacePool = $runspacePool 


    [Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property @{ 
     Runspace = $powershell.BeginInvoke() 
     PowerShell = $powershell 
    } 
    $runspaceCollection 
    } 


    While($runspaceCollection){ 
    Foreach($runspace in $runspaceCollection.ToArray()){ 
    If($runspace.Runspace.IsCompleted){ 
    $runspace.PowerShell.EndInvoke($runspace.Runspace) 
    $runspace.PowerShell.Dispose() 
    $runspaceCollection.Remove($runspace) 
    } 
    } 
    } 
} 

運行空間代碼來自這些指南的混合:

http://blogs.technet.com/b/heyscriptingguy/archive/2013/09/29/weekend-scripter-max-out-powershell-in-a-little-bit-of-time-part-2.aspx

http://newsqlblog.com/2012/05/22/concurrency-in-powershell-multi-threading-with-runspaces/

我希望有人能幫助我,並告訴我在哪裏/爲什麼我失敗了。謝謝!

+0

'$ objListboxLeft','$ objListboxCenter'和'$ objListboxRight'不運行空間存在,這可能就是它的失敗。從ScriptBlock返回一個對象 –

+0

我想你可以通過使用[powershell jobs](https://technet.microsoft.com/en-us/library/hh847805.aspx)來簡化你的腳本。類似'invoke-command -computername $ computers -scriptblock {#check winrm localy} -asjob' –

+0

@Kayasax仍然無法解決他嘗試修改執行範圍/ runspace/process中不存在的對象的問題 –

回答

1

嗯,感謝提示,但問題是更基本。

我試圖讓我的數據在錯誤的位置。另外,我簡化了腳本。我不再在函數中調用函數。注1:我沒有意識到我可以/需要在我的腳本塊中爲運行空間使用返回值。注意2:我現在正在收集我的數據並將其插入我的列表框(或者我曾經想過的地方)中,在while循環內我的函數結束處 - 我基本上建立了我的運行空間。

注3:我參考的所有「GUI部件」都位於不同的文件中,並存在!

我有時間限制在大約20秒(幾乎前5分鐘)

我使用的線程數是位隨機,它是最快的作品組合之一。

代碼:

function multiCheckMachine($computers){ 
    $ErrorActionPreference = "Stop" 

    $runspaceCollection = @() 
    $runspacePool = [RunspaceFactory]::CreateRunspacePool(1,50) 
    $runspacePool.open() 

    $scriptBlock = { 
    Param($item) 
    $FQDNitem = "$item.domain.com" 
    $address = nslookup $FQDNitem 

    if($address -like "addresses*"){ 
     $address = $address[5] -replace ".* ","" 
    }else{ 
     $address = $address[4] -replace ".* ","" 
    } 

    $con = ping -n 1 $address 
    if($con[2] -like "*Bytes*"){ 
     $winRM = test-wsman -ComputerName $item 
     if($winRM){ 
     return "$item.winRM" 
     }else{ 
     return "$item.NOremote" 
     } 

    }else{ 
     return "$item.offline" 
    } 
    } 

    Foreach($item in $computers){ 
    $powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item) 
    $powershell.runspacePool = $runspacePool 


    [Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property @{ 
     Runspace = $powershell.BeginInvoke() 
     PowerShell = $powershell 
    } 
    } 

    While($runspaceCollection){ 
    Foreach($runspace in $runspaceCollection.ToArray()){ 
    If($runspace.Runspace.IsCompleted){ 

     if($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*winrm"){ 
     [void] $objListboxOnline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0]) 

     }elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*NOremote"){ 
     [void] $objListboxNoWinRM.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0]) 

     }elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*offline"){ 
     [void] $objListboxOffline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0]) 
     } 

    $runspace.PowerShell.Dispose() 
    $runspaceCollection.Remove($runspace) 
    } 
    } 
    } 
}