PowerShell How To Ping a List of Computers

Administrator 6 Replies

This quick free lesson in PowerShell teaches you how to use the ping class to get a list of offline computers.  It is fast and easy, and the results are much easier to work with than using ping.exe.

Using the .Net Ping Class

PowerShell is built for speed, and it leverages the .Net framework to make this happen. 

To check the computers status, a Ping request is sent to each computer in a list. 

To start pinging, an object of the Ping class is instantiated:

$ping = new-object system.net.networkinformation.ping

Easy, right?

This avoids having to use the sloppy mess of processing through the text returned by ping.exe.

What is the difference?

By using a .Net object for the ping results, we can still use the object that is returned.  We can save the objects themselves and reference them back later.  The beauty of PowerShell.  The Power.  We want (and get) much more information.  The results of

ping 192.168.1.1

is a wall of text (an array of 11 strings, actually,) while the result of

$ping.send(“192.168.1.1”)

Is a .Net object of the "system.net.networkinformation.pingreply” class.  A pingreply has a property (named ‘status’) that tells us if the ping was successful or not; the address of the ping; and the miliseconds that it takes to get the reply.

To get results that are usable, keep your ping replies in a variable of results, like this:

$pingreturns = $ping.send(“192.168.1.1”)

Alright, we’ve got the base now for finding out if the computer is reachable.

Get Your Computer List Ready

The list of computers we want to ping.  You don’t have to limit your list to only computers. If the network device has Internet Control Message Protocol (ICMP) available (most do) and turned on (depends), it will return pings when they are received. You could ping network printers, or routers, for example.

Here are some examples of loading the ping list:

Get Computer List From Textfile

If you have several computers that you want to check frequently, add them to a text file so it’s easy to save, and easy to update the file instead of modifying the script.

“computer1”,”computer2”,”192.168.1.100”,”192.168.1.1” | out-file c:\users\public\documents\pinglist.txt

Now you’ve got a text file.  Quake with fear, bitches!  Note the use of hostnames and IP Addresses.  It’s fine to do that, you can mix and match.  That list is 4 computers, not a collection of 2 computers listed by hostname and IP.

Update the list of computers as needed.

To load the list of computers:

$complist = gc c:\users\public\documents\pinglist.txt

Get Computer List Manually

$complist = “computer1”, “computer2”

Easy, simple, and easy.  To change the list, you’d change it in the script itself. 

Get Computer List From Other Parts Of The Script

$servers = get-qadcomputer –service domain.com *serv*

$complist = $servers | select name

This seems normal, but it’s actually different, because you’re saving a list of objects into $complist, instead of a list of strings.  Here’s the difference

PS C:\ScriptGenius> $stringlist = "Computer1", "Computer2"
PS C:\ScriptGenius> $stringlist[0]
Computer1
PS C:\ScriptGenius> $stringlist[0].gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     String                                   System.Object

Compare that to the item in the object list

PS C:\ScriptGenius> $objectlist = get-qadcomputer *work* | select name
PS C:\ScriptGenius> $objectlist[0]

Name
—-
SOFTGRIDWORK2

PS C:\ScriptGenius> $objectlist[0].gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     False    PSCustomObject                           System.Object

While the two seem at first to be the same:

$ping.send($stringlist[0])

Works.

$ping.send($objectlist[0])

Does not, but it is at least salvageable.  To make that ping work,  the name property of the psCustomObject (the computer account returned by get-qadcomputer) must be referenced.

$ping.send($objectlist[0].name)

Works.

Get Computer List From an IP Range

This will do an IP sweep for a subnet, pinging along the way.

1..254 | % {$ping.send(“192.168.1.$_”) | select address, status}

Putting it All Together

Now that we’ve seen the pieces, here’s how it all works together.

$computers = get-content C:\scriptgenius\computers.txt

$ping = new-object system.net.networkinformation.ping

$pingreturns = @()

foreach ($entry in $computers) {

  $pingreturns += $ping.send($entry)

}

An array is used here to collect multiple ping results.  When completed, this can be used like this.

$pingreturns[4].status

or

$pingreturns | ? {$_.status –ne “success”} | select address

Instead of piping that to “select address” we could just as easily take action on those failed IP addresses.  Like sending the list of offline computers to the administrative team on on-call person via email.

6 thoughts on “PowerShell How To Ping a List of Computers

  1. Poshoholic

    If you are using PowerShell 2.0 you should use Test-Connection instead of System.Net.NetworkInformation.Ping. Knowing how to do something using the .NET Framework is great and very complimentary to PowerShell, but knowing how to do it in native PowerShell commands is even better.

    Then your test to see which computers are not responding becomes this one-liner:

    Get-Content C:\ScriptGenius\computers.txt | Where-Object {-not (Test-Connection -Count 2 -ComputerName $_ -ErrorAction SilentlyContinue)}

    Or if you’re performing some tasks against network computers and you want to make sure they are pingable first, you can do something like this:

    Get-Content C:\ScriptGenius\computers.txt | Where-Object {Test-Connection -Count 2 -ComputerName $_ -ErrorAction SilentlyContinue} | ForEach-Object { … }

    Reply
    1. riffshredder

      As a default stance, I agree that doing something built-in to a language is much better than using something else. In this case, however, after a few minutes of comparing the use of Test-Connection and the .Net method it seems to me that the .Net method is much more useful, not to mention faster.

      The use of background jobs isn’t useful for my specific situation, either. I probably won’t use it for checking more than one system at a time and most of the computers I’ll will check will have remoting disabled by default which is required per the technet site (http://technet.microsoft.com/en-us/library/hh849808.aspx) quoted below:

      “Note: To use this parameter, the local and remote computers must be configured for remoting and, on Windows Vista and later versions of Windows, you must open Windows PowerShell with the “Run as administrator” option. For more information, see about_Remote_Requirements.”

      For my use-case, the “Run as administrator” requirement is also not preferred.

      I am fairly new to PowerShell (using v2.0) so I could be missing some deeper issues here, but for my use-case, .Net seems the better solution.

      If anyone is still paying any attention to this thread, and I have made any errors, please let me know! Thanks!

      Reply
  2. Tobias

    pinging systems sequentially can take enourmous time. Use background jobs instead. Test-Connection accepts an array of computer names or IP addresses and supports -asJob, so you can transfer it to the background and have it check connectivity in parallel rather than subsequentially. This can reduce time from 5 minutes to 5 seconds.

    Reply
  3. patrick burwell

    does not appear to function Tobias:

    The term ‘.’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
    again.
    At c:\utils\pstools\PingComputers.ps1:3 char:19
    + ForEach-Object { . <<<< }
    + CategoryInfo : ObjectNotFound: (.:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Reply
  4. BigFoot78

    I’m new to Powershell scripting and others alike…

    I need to get the IP address and status back on a ping (reply, request timed out) on a large list of hostnames, 6000 to be exact.

    How would I get this list to generate with columns only showing the Host Name, the IP address, then for it to say Yes/No on Reply back…

    Reply

Whats Your Take?