In this week’s Prof. PowerShell column, I have an article on using the Test-Connection in Windows PowerShell. I thought it was pretty straightforward, but I didn’t take problems into account. I received an email asking what to do about error messages. For example, what if you have a computername in the list that can’t be resolved to an IP address? At first I thought you could use a traditional Trap, but after a little testing that’s not really going to give you what you want, I think. Here’s how I would handle it.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Now you can certainly use a Trap statement. You’ll need to use the –ErrorAction common parameter with Test-Connection cmdlet. That’s what I would do with most cmdlets. But in this case, I’m probably going to use it expecting a boolean value of True or False. The cmdlet is a wrapper for the Win32_PingStatus class and as such will attempt to resolve computernames. You can use an IP address for the computername, but you’ll get the same type of error if the computer is down.
Instead, I’ll simply tell Test-Connection to ignore any exception and keep on rolling. I can (probaby) safely assume that if there was an exception that the computer is “down” or I do not have a valid connection, which is the whole point of the cmdlet anyway, right?
$computers=@("172.16.10.69","godot7","foo","client1","serenity") foreach ($computername in $computers) { if (Test-Connection $computername -erroraction silentlyContinue ) { write-host "$computername UP" -foregroundColor Green } else { write-host "$computername DOWN" -ForegroundColor RED }
On my network some of these computers are valid and some are not. I don’t really care why a computer fails the connection test and I’m not sure I can get that information anyway from the underlying exception. The exception is the same, although the message does vary. Here’s almost the same code with the addition of a Trap statement.
$computers=@("172.16.10.69","godot7","foo","client1","serenity") foreach ($computername in $computers) { Trap { write-warning "Error Trapped for $computername" write-warning $_.Exception.Message Continue } if (Test-Connection $computername -erroraction stop ) { write-host "$computername UP" -foregroundColor Green } else { write-host "$computername DOWN" -ForegroundColor RED } }
The other significant change is that I changed the ErrorAction to Stop so that the exception is caught by the trap. The Trap is part of the ForEach construct so that PowerShell will continue with the next command in the same scope as the trap.
Obviously there are many ways you can use Test-Connection and I won’t swear that these ideas will work in all situations, absolutely. But hopefully it will give you a place to start.
Also useful is:
$computers=”PC1″,”PC2″,”PC”|select @{Name=’ComputerName’;Expression={$_}}|test-connection -cou 1 -q
This is two, probably not combinable, techniques. Feed from array and name element on the fly. Use -Quiet to surpess errors and return a boolean.
Just stumbled on it yesterday.
Agree with JV about the Quiet parameter. It suppresses all errors and returns $true if any pings succeeded and $false if all failed. So you can just do something like this:
$computers | foreach { if(Test-Connection $_ -Quiet) { write-host “$_ is up” } }
I was working on a similar function to produce a list of computers in AD to include a ping test. I wanted to provide more details when test-connection failed so I included $error[0].exception in the Else. Output is great for cases where there is no DNS entry but pretty generic otherwise when it returns “Error due to lack of resources”.