How to Use Multithreading script

后端 未结 2 503
野趣味
野趣味 2020-12-19 22:23

I found this Multithreading script at http://www.get-blog.com/?p=189

Param($Command = $(Read-Host \"Enter the script file\"), 
    [Parameter(ValueFromPipeli         


        
相关标签:
2条回答
  • 2020-12-19 22:34

    This script, which I have adapted from the link and author in the synopsis, has good performance for me. I have modified it to take not only a range of ip addresses, but also an array of host names. Because of that, some of the variable names have poor names, but this is not production code so I have not invested in it beyond what I have below.

    function Global:Ping-IPRange {
        <#
        .SYNOPSIS
            Sends ICMP echo request packets to a range of IPv4 addresses between two given addresses.
    
        .DESCRIPTION
            This function lets you sends ICMP echo request packets ("pings") to 
            a range of IPv4 addresses using an asynchronous method.
    
            Therefore this technique is very fast but comes with a warning.
            Ping sweeping a large subnet or network with many swithes may result in 
            a peak of broadcast traffic.
            Use the -Interval parameter to adjust the time between each ping request.
            For example, an interval of 60 milliseconds is suitable for wireless networks.
            The RawOutput parameter switches the output to an unformated
            [System.Net.NetworkInformation.PingReply[]].
    
        .INPUTS
            None
            You cannot pipe input to this funcion.
    
        .OUTPUTS
            The function only returns output from successful pings.
    
            Type: System.Net.NetworkInformation.PingReply
    
            The RawOutput parameter switches the output to an unformated
            [System.Net.NetworkInformation.PingReply[]].
    
        .NOTES
            Author  : G.A.F.F. Jakobs
            Created : August 30, 2014
            Version : 6
    
        .EXAMPLE
            Ping-IPRange -StartAddress 192.168.1.1 -EndAddress 192.168.1.254 -Interval 20
    
            IPAddress                                 Bytes                     Ttl           ResponseTime
            ---------                                 -----                     ---           ------------
            192.168.1.41                                 32                      64                    371
            192.168.1.57                                 32                     128                      0
            192.168.1.64                                 32                     128                      1
            192.168.1.63                                 32                      64                     88
            192.168.1.254                                32                      64                      0
    
            In this example all the ip addresses between 192.168.1.1 and 192.168.1.254 are pinged using 
            a 20 millisecond interval between each request.
            All the addresses that reply the ping request are listed.
    
        .EXAMPLE
            Ping-IPRange -HostName "host1"
            Ping-IPRange -HostName @('host1', 'host2')
            Ping-IPRange -HostName @('www.microsoft.com', 'www.google.com')
    
        .LINK
            http://gallery.technet.microsoft.com/Fast-asynchronous-ping-IP-d0a5cf0e
    
        #>
        [CmdletBinding(ConfirmImpact='Low')]
        Param(
            [parameter(Mandatory = $true, Position = 0, ParameterSetName='range')]
            [System.Net.IPAddress]$StartAddress,
            [parameter(Mandatory = $true, Position = 1, ParameterSetName='range')]
            [System.Net.IPAddress]$EndAddress,
            [parameter(Mandatory = $true, Position = 0, ParameterSetName='list')]
            [string[]]$HostName,
            [int]$Interval = 30,
            [Switch]$RawOutput = $false
        )
    
        $timeout = 2000
    
        function New-Range ($start, $end) {
            $addrList = [System.Collections.ArrayList]::new()
    
            [byte[]]$BySt = $start.GetAddressBytes()
            [Array]::Reverse($BySt)
            [byte[]]$ByEn = $end.GetAddressBytes()
            [Array]::Reverse($ByEn)
            $i1 = [System.BitConverter]::ToUInt32($BySt,0)
            $i2 = [System.BitConverter]::ToUInt32($ByEn,0)
            for($x = $i1;$x -le $i2;$x++){
                $ip = ([System.Net.IPAddress]$x).GetAddressBytes()
                [Array]::Reverse($ip)
                $null = $addrList.Add([System.Net.IPAddress]::Parse($($ip -join '.')))
            }
    
            ,$addrList
        }
    
        if ($HostName)
        {
            $IPrange = @($HostName)
        }
        else
        {
            [System.Collections.ArrayList]$IPrange = New-Range $StartAddress $EndAddress
        }
    
        $IpTotal = $IPrange.Count
    
        Get-Event -SourceIdentifier "ID-Ping*" | Remove-Event
        Get-EventSubscriber -SourceIdentifier "ID-Ping*" | Unregister-Event
    
        $index = 0
        foreach ($ip in $IPrange){
            if ($HostName)
            {
                [string]$VarName = "Ping_" + $ip + "_" + [guid]::NewGuid().ToString()
            }
            else
            {
                [string]$VarName = "Ping_" + $ip.Address
            }
    
            New-Variable -Name $VarName -Value (New-Object System.Net.NetworkInformation.Ping)
    
            Register-ObjectEvent -InputObject (Get-Variable $VarName -ValueOnly) -EventName PingCompleted -SourceIdentifier "ID-$VarName"
    
            (Get-Variable $VarName -ValueOnly).SendAsync($ip,$timeout,$VarName)
    
            try{
    
                $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count
    
            }catch [System.InvalidOperationException]{
                Write-Verbose "Ping-IPrange : InvalidOperationException" -Verbose
            }
            finally{
                Remove-Variable $VarName
            }
    
            #$index = [array]::indexof($IPrange,$ip)
    
            if ($HostName)
            {
                Write-Progress -Activity "Sending ping to" -Id 1 -status $ip -PercentComplete (($index / $IpTotal)  * 100)
            }
            else
            {
                Write-Progress -Activity "Sending ping to" -Id 1 -status $ip.IPAddressToString -PercentComplete (($index / $IpTotal)  * 100)
            }
    
            Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($index - $pending) -PercentComplete (($index - $pending)/$IpTotal * 100)
    
            Start-Sleep -Milliseconds $Interval
    
            $index++
        }
    
        Write-Progress -Activity "Done sending ping requests" -Id 1 -Status 'Waiting' -PercentComplete 100 
    
        While($pending -lt $IpTotal){
    
            Wait-Event -SourceIdentifier "ID-Ping*" | Out-Null
    
            Start-Sleep -Milliseconds 10
    
            $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count
    
            Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($IpTotal - $pending) -PercentComplete (($IpTotal - $pending)/$IpTotal * 100)
        }
    
        if($RawOutput){
    
            $Reply = Get-Event -SourceIdentifier "ID-Ping*" | ForEach { 
                If($_.SourceEventArgs.Reply.Status -eq "Success"){
                    $_.SourceEventArgs.Reply
                }
                Unregister-Event $_.SourceIdentifier
                Remove-Event $_.SourceIdentifier
            }
    
        }else{
            $events = Get-Event -SourceIdentifier "ID-Ping*"
            $Reply = [System.Collections.ArrayList]::new()
    
            $i = 0
            foreach ($event in $events) { 
                If($event.SourceEventArgs.Reply.Status -eq "Success"){
                    if ($HostName)
                    {
                        $null = $Reply.Add(
                            [PSCustomObject]@{
                                "HostName" = $HostName[$i]
                                "IPAddress" = $event.SourceEventArgs.Reply.Address
                                "Bytes" = $event.SourceEventArgs.Reply.Buffer.Length
                                "Ttl" = $event.SourceEventArgs.Reply.Options.Ttl
                                "ResponseTime" = $event.SourceEventArgs.Reply.RoundtripTime
                            }
                        )
                    }
                    else
                    {
                        $null = $Reply.Add(
                            [PSCustomObject]@{
                                "IPAddress" = $event.SourceEventArgs.Reply.Address
                                "Bytes" = $event.SourceEventArgs.Reply.Buffer.Length
                                "Ttl" = $event.SourceEventArgs.Reply.Options.Ttl
                                "ResponseTime" = $event.SourceEventArgs.Reply.RoundtripTime
                            }
                        )
                    }
                }
                else{
                    $addr = ($event.SourceIdentifier -split '_')[1]
                    $ip = ((([System.Net.IPAddress]$addr).IPAddressToString).Split('.'))
                    [Array]::Reverse($ip)
                    $ip = $ip -join '.'
    
                    if ($HostName)
                    {
                        $null = $Reply.Add(
                            [PSCustomObject]@{
                                "HostName" = $HostName[$i]
                                "IPAddress" = '0.0.0.0'
                                "Bytes" = -1
                                "Ttl" = -1
                                "ResponseTime" = -1
                            }
                        )
                    }
                    else
                    {
                        $null = $Reply.Add(
                            [PSCustomObject]@{
                                "IPAddress" = $ip
                                "Bytes" = -1
                                "Ttl" = -1
                                "ResponseTime" = -1
                            }
                        )
                    }
                }
                Unregister-Event $event.SourceIdentifier
                Remove-Event $event.SourceIdentifier
                $i++
            }
        }
    
        if($Reply -eq $Null){
            Write-Verbose "Ping-IPrange : No ip address responded" -Verbose
        }
    
        return ,$Reply
    }
    
    0 讨论(0)
  • 2020-12-19 22:51

    You can ping hosts asynchronously with [System.Net.NetworkInformation.Ping], no need to go crazy with runspaces. Moreover it will ping the host once, so it will be way much faster than test-connection. Below is a sample for a batch of hosts (about 90). I guess it's not a good idea to load 100K at once, probably split it in smaller batches and do one by one.

    $hosts = "www.facebook.com,www.twitter.com,www.youtu.be,www.google.com,www.youtube.com,www.instagram.com,www.linkedin.com,www.pinterest.com,www.wordpress.com,www.blogspot.com,www.apple.com,www.adobe.com,www.tumblr.com,www.amazon.com,www.vimeo.com,www.flickr.com,www.microsoft.com,www.yahoo.com,www.godaddy.com,www.qq.com,www.vk.com,www.reddit.com,www.baidu.com,www.nytimes.com,www.buydomains.com,www.wp.com,www.statcounter.com,www.jimdo.com,www.blogger.com,www.github.com,www.weebly.com,www.soundcloud.com,www.myspace.com,www.addthis.com,www.theguardian.com,www.cnn.com,www.stumbleupon.com,www.gravatar.com,www.digg.com,www.addtoany.com,www.creativecommons.org,www.paypal.com,www.yelp.com,www.imdb.com,www.huffingtonpost.com,www.feedburner.com,www.issuu.com,www.wixsite.com,www.wix.com,www.dropbox.com,www.forbes.com,www.amazonaws.com,www.washingtonpost.com,www.bluehost.com,www.etsy.com,www.go.com,www.msn.com,www.wsj.com,www.weibo.com,www.fc2.com,www.eventbrite.com,www.parallels.com,www.ebay.com,www.livejournal.com,www.reuters.com,www.taobao.com,www.typepad.com,www.bloomberg.com,www.elegantthemes.com,www.eepurl.com,www.usatoday.com,www.about.com,www.medium.com,www.macromedia.com,www.xing.com,www.bing.com,www.time.com,www.tripadvisor.com,www.aol.com,www.constantcontact.com,www.latimes.com,www.list-manage.com,www.webs.com,www.opera.com,www.live.com,www.bandcamp.com,www.bbc.com,www.businessinsider.com,www.dailymotion.com,www.cpanel.com,www.disqus.com,www.sina.com.cn,www.spotify.com,www.wired.com,www.googleusercontent.com"
    $hosts = $hosts -split ","
    
    $tasks = @{}
    foreach ($h in $hosts) { $tasks[$h] = [System.Net.NetworkInformation.Ping]::new().SendPingAsync($h)}
    
    Write-Host "Waiting for batch is completed" -NoNewline
    while($false -in $tasks.Values.IsCompleted) {sleep -Milliseconds 300; Write-Host "." -NoNewline}
    
    $result = foreach($h in $hosts) {
    $r = $tasks[$h].Result
    [PSCustomObject]@{
     host = $h
     address = $r.Address.IPAddressToString
     status = if($r.Address.IPAddressToString){$r.Status}else{"Failed"}
     time = $r.RoundtripTime
     bytes = $r.Buffer.Count
     ttl = $r.Options.Ttl
      }
    }
    
    
    $result | Format-Table -AutoSize
    
    0 讨论(0)
提交回复
热议问题