Test-Host (WMI Ping -or Port Check)
I often find (specifically when using WMI) the need to ping the machine first before performing any queries. WMI takes FOREVER to timeout. I decided that I should use a script/function to test a host before passing it down the pipe.
There are a couple of problems with this approach that I had to consider.
1) How do I know what to test without corrupting the pipe or using foreach?
- For this I added a “-property” parameter that would allow the user to pick what property to check against, but still output the entire object that was inputted.
2) What about firewalls that block ping?
- Added TestPort function that does a TCP connect and returns $true or $false
3) What if I want a conditional port check.
- Added the ability to Change the Default Port for TCP Connection Test
Here is the script that I came up with and some of things it does.
Parameters
- $property: The Property to Ping or Test (Default is none.)
- $tport: The Port to test against (Default is 135. Used with -port)
- $timeout: The timeout for the connection (Default is 1000 ms, Used with -port)
- [switch]$port: Switch to Test a port instead of Ping
- [switch]$verbose: Provides Verbose Output.
Features
- Will Ping ‘$_’ by default
- Can pass the property that contains the Host to test using -property
- Can use -port to test a port instead of ping. (Uses TCP)
- Maintains the Object that is tested and passes it down the pipe if connection is passed.
A Demo of the script in action
Best Viewed Full Screen
Get the Flash Player to see this player.
Script CODE
Begin{
function TestPort {
Param($srv)
$error.Clear()
$ErrorActionPreference = "SilentlyContinue"
$tcpclient = new-Object system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($srv,$tport,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
# Traps
trap {if($verbose){Write-Host "General Exception"};return $false}
trap [System.Net.Sockets.SocketException]
{
if($verbose){Write-Host "Exception: $($_.exception.message)"}
return $false
}
if(!$wait)
{
$tcpclient.Close()
if($verbose){Write-Host "Connection Timeout"}
return $false
}
else
{
$tcpclient.EndConnect($iar) | out-Null
$tcpclient.Close()
}
if(!$error[0]){return $true}
}
function PingServer {
Param($MyHost)
$pingresult = Get-WmiObject win32_pingstatus -f "address=’$MyHost’"
if($pingresult.statuscode -eq 0) {$true} else {$false}
}
}
Process{
if($_)
{
if($port)
{
if($property)
{
if(TestPort $_.$property){$_}
}
else
{
if(TestPort $_){$_}
}
}
else
{
if($property)
{
if(PingServer $_.$property){$_}
}
else
{
if(PingServer $_){$_}
}
}
}
}
If you want this as a function use this code
Param($property,$tport=135,$timeout=1000,[switch]$port,[switch]$verbose)
Begin{
function TestPort {
Param($srv)
$error.Clear()
$ErrorActionPreference = "SilentlyContinue"
$tcpclient = new-Object system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($srv,$tport,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne($timeout,$false)
# Traps
trap {if($verbose){Write-Host "General Exception"};return $false}
trap [System.Net.Sockets.SocketException]
{
if($verbose){Write-Host "Exception: $($_.exception.message)"}
return $false
}
if(!$wait)
{
$tcpclient.Close()
if($verbose){Write-Host "Connection Timeout"}
return $false
}
else
{
$tcpclient.EndConnect($iar) | out-Null
$tcpclient.Close()
}
if(!$error[0]){return $true}
}
function PingServer {
Param($MyHost)
$pingresult = Get-WmiObject win32_pingstatus -f "address=’$MyHost’"
if($pingresult.statuscode -eq 0) {$true} else {$false}
}
}
Process{
if($_)
{
if($port)
{
if($property)
{
if(TestPort $_.$property){$_}
}
else
{
if(TestPort $_){$_}
}
}
else
{
if($property)
{
if(PingServer $_.$property){$_}
}
else
{
if(PingServer $_){$_}
}
}
}
}}
