2015-10-27 81 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) 
    } 
    } 
    } 
}