0

改编一个脚本来执行多种功能,从测试连接开始收集数据,将达到 6000 多台机器,所以我使用的是从以下站点改编的 RunspacePools;

http://learn-powershell.net/2013/04/19/sharing-variables-and-live-objects-between-powershell-runspaces/

数据出来如下,我想把它排序成一个数组(我认为这是术语),所以我可以通过结果对数据进行排序。这将适用于从序列号到 IAVM 数据的多个其他功能。

有什么办法可以使用逗号分隔的数据并将下面的值吐到列中?IE

Name    IPAddress    ResponseTime    Subnet
x        qwe           qweeqwe        qweqwe

附加值目前并不那么重要,只是添加和提取值的能力。

Name                           Value                                                                                                                        
—-                           —–                                                                                                                        
x-410ZWG                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-410ZWG",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-47045Q                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-47045Q",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-440J26                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-440J26",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-410Y45                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-410Y45",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-DJKVV1                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-DJKVV1",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
nonexistant                                                                                                                                                 
x-DDMVV1                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-DDMVV1",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-470481                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-470481",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-DHKVV1                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-DHKVV1",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-430XXF                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-430XXF",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-DLKVV1                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-DLKVV1",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-410S86                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-410S86",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-SCH004                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-SCH004",BufferSize=32,NoFragmentation=false,RecordRoute=0,…
x-431KMS                                                                                                                                             
x-440J22                \\x-DHMVV1\root\cimv2:Win32_PingStatus.Address="x-440J22",BufferSize=32,NoFragmentation=false,RecordRoute=0,…

感谢您的帮助!

当前代码

Function Get-RunspaceData {
    [cmdletbinding()]
    param(
        [switch]$Wait
    )
    Do {
        $more = $false         
        Foreach($runspace in $runspaces) {
            If ($runspace.Runspace.isCompleted) {
                $runspace.powershell.EndInvoke($runspace.Runspace)
                $runspace.powershell.dispose()
                $runspace.Runspace = $null
                $runspace.powershell = $null                 
            } ElseIf ($runspace.Runspace -ne $null) {
                $more = $true
            }
        }
        If ($more -AND $PSBoundParameters['Wait']) {
            Start-Sleep -Milliseconds 100
        }   
        #Clean out unused runspace jobs
        $temphash = $runspaces.clone()
        $temphash | Where {
            $_.runspace -eq $Null
        } | ForEach {
            Write-Verbose ("Removing {0}" -f $_.computer)
            $Runspaces.remove($_)
        }  
        Write-Host ("Remaining Runspace Jobs: {0}" -f ((@($runspaces | Where {$_.Runspace -ne $Null}).Count)))             
    } while ($more -AND $PSBoundParameters['Wait'])
}


#Begin
#What each runspace will do
$ScriptBlock = {
    Param ($computer,$hash)
    $Ping = test-connection $computer -count 1 -ea 0
    $hash[$Computer]= $Ping
        }

#Setup the runspace
$Script:runspaces = New-Object System.Collections.ArrayList   
# Data table for all of the runspaces
$hash = [hashtable]::Synchronized(@{})
$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspacepool = [runspacefactory]::CreateRunspacePool(1, 100, $sessionstate, $Host)
$runspacepool.Open() 

#Process
ForEach ($Computer in $Computername) {
    #Create the powershell instance and supply the scriptblock with the other parameters 
    $powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($computer).AddArgument($hash)

    #Add the runspace into the powershell instance
    $powershell.RunspacePool = $runspacepool

    #Create a temporary collection for each runspace
    $temp = "" | Select-Object PowerShell,Runspace,Computer
    $Temp.Computer = $Computer
    $temp.PowerShell = $powershell

    #Save the handle output when calling BeginInvoke() that will be used later to end the runspace
    $temp.Runspace = $powershell.BeginInvoke()
    Write-Verbose ("Adding {0} collection" -f $temp.Computer)
    $runspaces.Add($temp) | Out-Null               
}

# Wait for all runspaces to finish
#End
Get-RunspaceData -Wait 
$stoptimer = Get-Date 
#Display info, and display in GridView
Write-Host
Write-Host "Availability check complete!" -ForegroundColor Cyan
"Execution Time: {0} Minutes" -f [math]::round(($stoptimer – $starttimer).TotalMinutes , 2)
$hash | ogv
4

1 回答 1

2

当您使用运行空间时,您为运行空间编写脚本块的方式与编写函数的方式几乎相同。您将希望返回的任何内容写入管道,然后将其分配给一个变量,将其通过管道传输到另一个 cmdlet 或函数,或者让它输出到控制台。不同之处在于,虽然函数自动返回结果,但它们在运行空间输出缓冲区中收集运行空间,并且在您对运行空间句柄执行 .EndInvoke() 之前不会返回。

作为一般规则,Powershell 脚本的目标是(或应该是)创建对象,而使用运行空间的目标是通过多线程加速进程。您可以将运行空间中的字符串数据返回到主脚本,然后使用它在那里创建对象,但这将是一个单线程进程。在运行空间中创建对象,使其也是多线程的。

这是一个使用运行空间池对 C 类子网执行 pingsweep 的示例脚本:

Param (
 [int]$timeout = 200
 )

 $scriptPath = (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)


While (
        ($network -notmatch "\d{1,3}\.\d{1,3}\.\d{1,3}\.0") -and -not
        ($network -as [ipaddress])
       )

   { $network = read-host 'Enter network to scan (ex. 10.106.31.0)' }

$scriptblock = 
{
  Param (
   [string]$network,
   [int]$LastOctet,
   [int]$timeout
   )

  $options = new-object system.net.networkinformation.pingoptions
  $options.TTL = 128
  $options.DontFragment = $false
  $buffer=([system.text.encoding]::ASCII).getbytes('a'*32)
  $Address = $($network.trim("0")) + $LastOctet
  $ping = new-object system.net.networkinformation.ping
  $reply = $ping.Send($Address,$timeout,$buffer,$options)

  Try { $hostname = ([System.Net.Dns]::GetHostEntry($Address)).hostname }
  Catch { $hostname = 'No RDNS' }

  if ( $reply.status -eq 'Success' )
    { $ping_result = 'Yes' }

   else { $ping_result = 'No' }

  [PSCustomObject]@{
   Address = $Address
   Ping    = $ping_result
   DNS     = $hostname
   }
}

$RunspacePool = [RunspaceFactory]::CreateRunspacePool(100,100)
$RunspacePool.Open()
$Jobs = 
   foreach ( $LastOctet in 1..254 )
    {
     $Job = [powershell]::Create().
            AddScript($ScriptBlock).
            AddArgument($Network).
            AddArgument($LastOctet).
            AddArgument($Timeout)
     $Job.RunspacePool = $RunspacePool

     [PSCustomObject]@{
      Pipe = $Job
      Result = $Job.BeginInvoke()
     }
}

Write-Host 'Working..' -NoNewline

Do {
   Write-Host '.' -NoNewline
   Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false)

Write-Host ' Done! Writing output file.'
Write-host "Output file is $scriptPath\$network.Ping.csv"

$(ForEach ($Job in $Jobs)
{ $Job.Pipe.EndInvoke($Job.Result) }) |
 Export-Csv $scriptPath\$network.ping.csv -NoTypeInformation

$RunspacePool.Close()
$RunspacePool.Dispose()

运行空间脚本对每个地址执行 ping,如果成功 ping,则尝试从 DNS 解析主机名。然后它根据该数据构建一个自定义对象,并将其输出到管道。最后,当 .EndInvoke() 在运行空间作业上完成并直接通过管道传输到 Export-CSV 时,这些对象会返回,但它可以很容易地输出到控制台,或保存到变量中。

于 2014-10-01T11:13:09.867 回答