Powershell运行空间不会执行

时间:2015-10-27 13:52:35

标签: multithreading powershell

我试图拉动的脚本让我感到有点失落。

简而言之:我想扫描我的域名计算机以获取WinRM连接 - 我可以做到这一点。问题是,完成需要5分钟 - 这就是我想要多线程完成任务的原因。

使用NON MULTITHREAD代码:

# 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做/将做的一小部分,但它是需要很长时间的部分。

我失败的runpace测试 - 我基本上没有得到任何结果。文本框中没有任何东西,我的命令行上没有输出,我基本上不知道我做错了什么。

多线程代码:

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

runpace代码来自这些指南的混合:

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/

我希望有人可以帮助我,告诉我在哪里/为什么失败。谢谢!

1 个答案:

答案 0 :(得分:1)

嗯,谢谢提示,但问题更为基础。

我试图将我的数据放在错误的位置。另外,我简化了我的脚本。我不再在函数中调用函数了。

注1:我没有意识到我可以/需要使用我的scriptblock中的返回值作为运行空间。

注意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)
    }
   }
  }
}