Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Ping IP Range

Posted on November 7, 2011April 25, 2014

Last week I came across a post on using PowerShell, or more specifically a .NET Framework class, to ping a range of computers in an IP subnet. The original post by Thomas Maurer is here. I added a comment. And after looking at this again I decided to take the ball and run with it a bit further. I'm a big proponent of PowerShell tools that are object oriented and that can add real value to the pipeline. To that end I wrote Test-Subnet.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

My function is essentially a wrapper for the Test-Connection cmdlet. By using the cmdlet, I can take advantage of some built in parameters such as the number of pings to send, buffer size and time to live. I'm also going to take advantage of the -Quiet parameter which will return a simple True/False depending on whether the address can be pinged. Here's what the code looks like.

Function Test-Subnet {
[cmdletbinding()]

Param (
[Parameter(Position=0)]
[ValidatePattern("\d{1,3}\.\d{1,3}\.\d{1,3}")]
[string]$Subnet="172.16.10",
[Parameter(Position=1)]
[int[]]$Range=1..254,
[int]$Count=1,
[int]$Delay=1,
[int]$Buffer=32,
[int]$TTL=80,
[switch]$AsJob
)

Write-Verbose "Testing $subnet"
#define a scriptblock we can run as a job if necessary
$sb={
Param($range,$subnet,$count,$delay,$buffer,$ttl)
$range | foreach {
    $target="$subnet.$_"
    Write-verbose $target
    $ping=Test-Connection -ComputerName $target -count $count -Delay $delay -BufferSize $Buffer -TimeToLive $ttl -Quiet
    New-Object -TypeName PSObject -Property @{
        IPAddress=$Target
        Pinged=$ping
        TTL=$TTL
        Buffersize=$buffer
        Delay=$Delay
        TestDate=Get-date
    }
}
} #close scriptblock

if ($AsJob) {
    Write-Verbose "Creating a background job"
    Start-Job -ScriptBlock $sb -Name "Ping $subnet" -ArgumentList $range,$subnet,$count,$delay,$buffer,$ttl
}
else {
 #run the command normally
 Invoke-Command -ScriptBlock $sb -ArgumentList $range,$subnet,$count,$delay,$buffer,$ttl
}

} #end function

This is an advanced function. The download file includes comment based help. The main part of the script takes the range of host numbers and pipes them to a foreach construct.

$range | foreach {
    $target="$subnet.$_"

Each number in the range is "added" to the subnet to come up with target IP. So if the range is 1..5 and the subnet is 192.16.10 each time through I'll get targets 192.168.10.1 through 192.168.10.5. This address is passed to Test-Connection along with the other values from my function.

$ping=Test-Connection -ComputerName $target -count $count -Delay $delay -BufferSize $Buffer -TimeToLive $ttl -Quiet

Then for each target address, I use the New-Object cmdlet to create a custom object. The -Property parameter is a hash table that will be used as properties for the custom object.

 New-Object -TypeName PSObject -Property @{
        IPAddress=$Target
        Pinged=$ping
        TTL=$TTL
        Buffersize=$buffer
        Delay=$Delay
        TestDate=Get-date
    }

Most of these values are taken from the function's input values. Although I added a TestDate property to capture the current date and time in the event that you saving your ping results for later review.

The function could have been a simple wrapper but I took it a step further and added my own support to run it as a background job. The Test-Connection cmdlet has an -AsJob parameter. I could have structured my function to use it, but I wanted to show how you might add AsJob support for commands that don't support it natively.

The extra step you need is to turn your core command into a script block. Script blocks can accept parameters which I need to use. Otherwise, the variables wouldn't get resolved because of scope.

$sb={
Param($range,$subnet,$count,$delay,$buffer,$ttl)
$range | foreach {
    $target="$subnet.$_"
    Write-verbose $target
    $ping=Test-Connection -ComputerName $target -count $count -Delay $delay -BufferSize $Buffer -TimeToLive $ttl -Quiet
    New-Object -TypeName PSObject -Property @{
        IPAddress=$Target
        Pinged=$ping
        TTL=$TTL
        Buffersize=$buffer
        Delay=$Delay
        TestDate=Get-date
    }
}
} #close scriptblock

If I don't specify -AsJob, I'll run the script block using Invoke-Command and pass it a list of arguments.

Invoke-Command -ScriptBlock $sb -ArgumentList $range,$subnet,$count,$delay,$buffer,$ttl

But if I use -Asjob, then I'll pass the scriptblock to the Start-Job cmdlet.

if ($AsJob) {
    Write-Verbose "Creating a background job"
    Start-Job -ScriptBlock $sb -Name "Ping $subnet" -ArgumentList $range,$subnet,$count,$delay,$buffer,$ttl
}

Later I can retrieve the results and then slice and dice as much as I need to. The key takeaway is to always be thinking about objects in the pipeline.

For example, here I'm going to ping 192.168.10.100 through 192.168.10.200 and save the IP addresses that fail to a text file.

PS C:\> Test-Subnet 192.168.10 (100..200) | where {! $_.Pinged} | Select -expand IPAddress | out-file c:\work\ipfail.txt

Or maybe something like this where we pass the IP address to Get-WMIobject.

PS C:\> test-subnet -range (1..10) | where {$_.pinged} | 
>> foreach {get-wmiobject win32_operatingsystem -comp $_.IPAddress} | 
>> Select CSName,Caption
>>

I trust you get the idea.

Download Test-Subnet and let me know what you think.

UPDATE: A newer version of this function can be found at http://bit.ly/QLDJVX


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “Ping IP Range”

  1. Pingback: Test IP Subnet PowerShell Winform | The Lonely Administrator

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d