PoshCode Logo PowerShell Code Repository

Async Ping Sweep by AlphaSun 12 months ago
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/6294"></script>download | new post

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 switches 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[]].

Written by: gaff-jakobs
https://social.technet.microsoft.com/profile/gaff-jakobs/

  1. function Global:Ping-IPRange {
  2.     <#
  3.     .SYNOPSIS
  4.         Sends ICMP echo request packets to a range of IPv4 addresses between two given addresses.
  5.  
  6.     .DESCRIPTION
  7.         This function lets you sends ICMP echo request packets ("pings") to
  8.         a range of IPv4 addresses using an asynchronous method.
  9.  
  10.         Therefore this technique is very fast but comes with a warning.
  11.         Ping sweeping a large subnet or network with many switches may result in
  12.         a peak of broadcast traffic.
  13.         Use the -Interval parameter to adjust the time between each ping request.
  14.         For example, an interval of 60 milliseconds is suitable for wireless networks.
  15.         The RawOutput parameter switches the output to an unformated
  16.         [System.Net.NetworkInformation.PingReply[]].
  17.  
  18.     .INPUTS
  19.         None
  20.         You cannot pipe input to this function.
  21.  
  22.     .OUTPUTS
  23.         The function only returns output from successful pings.
  24.  
  25.         Type: System.Net.NetworkInformation.PingReply
  26.  
  27.         The RawOutput parameter switches the output to an unformated
  28.         [System.Net.NetworkInformation.PingReply[]].
  29.  
  30.     .NOTES
  31.         Author  : G.A.F.F. Jakobs
  32.         Created : August 30, 2014
  33.         Version : 6
  34.  
  35.     .EXAMPLE
  36.         Ping-IPRange -StartAddress 192.168.1.1 -EndAddress 192.168.1.254 -Interval 20
  37.  
  38.         IPAddress                                 Bytes                     Ttl           ResponseTime
  39.         ---------                                 -----                     ---           ------------
  40.         192.168.1.41                                 32                      64                    371
  41.         192.168.1.57                                 32                     128                      0
  42.         192.168.1.64                                 32                     128                      1
  43.         192.168.1.63                                 32                      64                     88
  44.         192.168.1.254                                32                      64                      0
  45.  
  46.         In this example all the ip addresses between 192.168.1.1 and 192.168.1.254 are pinged using
  47.         a 20 millisecond interval between each request.
  48.         All the addresses that reply the ping request are listed.
  49.  
  50.     .LINK
  51.         http://gallery.technet.microsoft.com/Fast-asynchronous-ping-IP-d0a5cf0e
  52.  
  53.     #>
  54.     [CmdletBinding(ConfirmImpact='Low')]
  55.     Param(
  56.         [parameter(Mandatory = $true, Position = 0)]
  57.         [System.Net.IPAddress]$StartAddress,
  58.         [parameter(Mandatory = $true, Position = 1)]
  59.         [System.Net.IPAddress]$EndAddress,
  60.         [int]$Interval = 30,
  61.         [Switch]$RawOutput = $false
  62.     )
  63.  
  64.     $timeout = 2000
  65.  
  66.     function New-Range ($start, $end) {
  67.  
  68.         [byte[]]$BySt = $start.GetAddressBytes()
  69.         [Array]::Reverse($BySt)
  70.         [byte[]]$ByEn = $end.GetAddressBytes()
  71.         [Array]::Reverse($ByEn)
  72.         $i1 = [System.BitConverter]::ToUInt32($BySt,0)
  73.         $i2 = [System.BitConverter]::ToUInt32($ByEn,0)
  74.         for($x = $i1;$x -le $i2;$x++){
  75.             $ip = ([System.Net.IPAddress]$x).GetAddressBytes()
  76.             [Array]::Reverse($ip)
  77.             [System.Net.IPAddress]::Parse($($ip -join '.'))
  78.         }
  79.     }
  80.    
  81.     $IPrange = New-Range $StartAddress $EndAddress
  82.  
  83.     $IpTotal = $IPrange.Count
  84.  
  85.     Get-Event -SourceIdentifier "ID-Ping*" | Remove-Event
  86.     Get-EventSubscriber -SourceIdentifier "ID-Ping*" | Unregister-Event
  87.  
  88.     $IPrange | foreach{
  89.  
  90.         [string]$VarName = "Ping_" + $_.Address
  91.  
  92.         New-Variable -Name $VarName -Value (New-Object System.Net.NetworkInformation.Ping)
  93.  
  94.         Register-ObjectEvent -InputObject (Get-Variable $VarName -ValueOnly) -EventName PingCompleted -SourceIdentifier "ID-$VarName"
  95.  
  96.         (Get-Variable $VarName -ValueOnly).SendAsync($_,$timeout,$VarName)
  97.  
  98.         Remove-Variable $VarName
  99.  
  100.         try{
  101.  
  102.             $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count
  103.  
  104.         }catch [System.InvalidOperationException]{}
  105.  
  106.         $index = [array]::indexof($IPrange,$_)
  107.    
  108.         Write-Progress -Activity "Sending ping to" -Id 1 -status $_.IPAddressToString -PercentComplete (($index / $IpTotal)  * 100)
  109.  
  110.         Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($index - $pending) -PercentComplete (($index - $pending)/$IpTotal * 100)
  111.  
  112.         Start-Sleep -Milliseconds $Interval
  113.     }
  114.  
  115.     Write-Progress -Activity "Done sending ping requests" -Id 1 -Status 'Waiting' -PercentComplete 100
  116.  
  117.     While($pending -lt $IpTotal){
  118.  
  119.         Wait-Event -SourceIdentifier "ID-Ping*" | Out-Null
  120.  
  121.         Start-Sleep -Milliseconds 10
  122.  
  123.         $pending = (Get-Event -SourceIdentifier "ID-Ping*").Count
  124.  
  125.         Write-Progress -Activity "ICMP requests pending" -Id 2 -ParentId 1 -Status ($IpTotal - $pending) -PercentComplete (($IpTotal - $pending)/$IpTotal * 100)
  126.     }
  127.  
  128.     if($RawOutput){
  129.        
  130.         $Reply = Get-Event -SourceIdentifier "ID-Ping*" | ForEach {
  131.             If($_.SourceEventArgs.Reply.Status -eq "Success"){
  132.                 $_.SourceEventArgs.Reply
  133.             }
  134.             Unregister-Event $_.SourceIdentifier
  135.             Remove-Event $_.SourceIdentifier
  136.         }
  137.    
  138.     }else{
  139.  
  140.         $Reply = Get-Event -SourceIdentifier "ID-Ping*" | ForEach {
  141.             If($_.SourceEventArgs.Reply.Status -eq "Success"){
  142.                 $_.SourceEventArgs.Reply | select @{
  143.                       Name="IPAddress"   ; Expression={$_.Address}},
  144.                     @{Name="Bytes"       ; Expression={$_.Buffer.Length}},
  145.                     @{Name="Ttl"         ; Expression={$_.Options.Ttl}},
  146.                     @{Name="ResponseTime"; Expression={$_.RoundtripTime}}
  147.             }
  148.             Unregister-Event $_.SourceIdentifier
  149.             Remove-Event $_.SourceIdentifier
  150.         }
  151.     }
  152.     if($Reply -eq $Null){
  153.         Write-Verbose "Ping-IPrange : No ip address responded" -Verbose
  154.     }
  155.  
  156.     return $Reply
  157. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me