Checking Server Availability in PowerShell
Originally published April 19, 2007
So...if you want to find out if a server is “around” before you start doing things to it, what do you do? If you are working from your desktop, you probably will start with a “ping” and then perhaps a “telnet server smtp” - if it's an SMTP server or “telnet server 389” if it is a DC.
You can do the same thing in a program/script. While most of my older code was written in VBScript, these days I'm doing most of my new code in PowerShell, with some of it in C#. Since you can access most of the .Net Framework in PowerShell, it makes some things really easy to do.
I still have my old habits though. When I first wanted to do this, I started out with WMI - because I knew that the Win32_PingStatus class existed, and I had used it many times in VBScript...so Version 1 of the PowerShell script looks like this:
$ip =”192.168.100.81”
$qry = ('select statuscode from win32_pingstatus where address="' + $ip + '"')
$rslt = gwmi –query “$qry”
if ($rslt.StatusCode –eq 0) {
write-host “ping worked”
}
else {
write-host “ping failed”
}
$rslt = $null
So that get's the ping done, and it works just fine. but now I want to open a TCP port. I've written C# programs that act as SMTP clients before, so I know that the .Net namespace I needed to use is System.Net.Sockets. So, no problem:
$port = 25
$socket = new-object System.Net.Sockets.TcpClient($ip, $port)
if ($socket –eq $null) {
write-host “couldn’t open socket to SMTP”
}
else {
write-host “got socket to SMTP”
$socket = $null
}
but this begs the question - if I'm using .Net for the sockets interface, mightn't there be something for pinging too? And of course, it turns out that there is. Using google against msdn.microsoft.com, I found the System.Net.NetworkInformation namespace that has a class named Ping. Excellent! So, we can rewrite our ping like this for Version 2:
$ip =”192.168.100.81”
$ping = new-object System.Net.NetworkInformation.Ping
$rslt = $ping.send($ip)
if ($rslt.status.tostring() –eq “Success”) {
write-host “ping worked”
}
else {
write-host “ping failed”
}
$ping = $null
Isn't that much nicer? Now, we can put both pieces of the script together, and we come up with the script below for Version 3 to complete our specified goal:
$ip =”192.168.100.81”
$ping = new-object System.Net.NetworkInformation.Ping
$rslt = $ping.send($ip)
if ($rslt.status.tostring() –eq “Success”) {
write-host “ping worked”
# if the ping works, try opening a socket to the SMTP port
$port = 25
$socket = new-object System.Net.Sockets.TcpClient($ip, $port)
if ($socket –eq $null) {
write-host “couldn’t open SMTP socket”
}
else {
write-host “got socket to SMTP”
$socket = $null
}
}
else {
write-host “ping failed”
}
$ping = $null
I hope this helps someone out there!