Practical PowerShell Uncategorized Connectivity Testing

Connectivity Testing

When writing scripts that download files or scrape websites for content, one of the weaknesses of such scripts comes down to whether or not the script can connect to the Internet and download the files needed. PowerShell has many methods for determining whether a connection can be made or not. We’ll explore these possibilities.

Test-Connection

Within PowerShell there is a cmdlet called Test-Connection. This can be used to reach out to a server to see if it is available. There are quite a few options that can be used with this cmdlet. We can specify these options:

BufferSize – default is 32 (bytes)
ComputerName – what server to check
Count – how many echo requests to send
Credential – if credentials are needed to send a ping request
DcomAuthentication – choose the level of authentication that WMI uses
Delay – delay between pings
Protocol – Dcom and Wsman are allowable choices
Quiet – Suppresses errors
Source – where to originate ping
ThrottleLimit – specifies a concurrent connection limit – 32 is the default.
TimeToLive – default is 80 seconds

For basic connection testing, we should be able to run a cmdlet like this:
[sourcecode language=”powershell”]
Test-Connection -ComputerName <IP or Computer Name><BR>
[/sourcecode]

How can we use this in a check for script processing:
[sourcecode language=”powershell”]
$Bad=0
$Good=0
Try {
$Test = Test-Connection -ComputerName 192.168.0.254 -ErrorAction STOP
$Good++
} Catch {
$Bad++
}
[/sourcecode]
If the connection is successful, then $Good would equal 1 and if it is not successful, $Bad would equal 1.

Successful Connection:

Unsuccessful Connection:

Networking Check

We can use this cmdlet to check network connections of a computer. Most computers will only have one NIC. When we run the cmdlet – Get-NetConnectionProfile – we see this result:

Sample Output:

If we are specifically looking for Internet connectivity, then we can specifically look at the IPv4Connectivity value. On a server that can reach the Internet, the value would indeed be ‘Internet’ as show above. If the network connection is missing it’s default gateway, then we should get a different result:

This test isn’t always the best test for Internet connectivity, but if the connection is valid and there is a default gateway, we should be able to check it with this:
[sourcecode language=”powershell”]
$Internetaccess = (Get-NetConnectionProfile -IPv4Connectivity Internet).ipv4connectivity
[/sourcecode]
If $InternetAccess = ‘Internet’ then there is a valid connection and downloads should work.

Ping Test (with PowerShell)

A common tool for troubleshooting in networking is PING. It can be used to assess whether a connection could be made to a remote device. If that device can be reached with ICMP packets, then this test will be valid. A common blocker for this test are firewalls and servers that block ICMP packet types.

Ping DC01

As we can see, in this case a ping test to an internal server works. We can also perform the same test to a known Internet entity like Google’s DNS servers:

Test-NetConnect

PowerShell provides a cmdlet that is much more advanced than PING, we have Test-NetConnection. From Microsoft:
“The Test-NetConnection cmdlet displays diagnostic information for a connection. It supports ping test, TCP test, route tracing, and route selection diagnostics. Depending on the input parameters, the output can include the DNS lookup results, a list of IP interfaces, IPsec rules, route/source address selection results, and/or confirmation of connection establishment.”
First, the ‘PING replacement’:
[sourcecode language=”powershell”]
Test-NetConnect DC01
[/sourcecode]

Same command, but to an external destination, again using Google’s DNS server as an example:
[sourcecode language=”powershell”]
Test-NetConnect 8.8.8.8
[/sourcecode]

Testing Port Availability:

Logging level:

While the detailed level setting for ‘InformationLevel’ will work for troubleshooting purposes, when it comes to practical application in a script, the ‘Quiet’ setting is a much better match.
Sample output:


Why Quiet is better?

[sourcecode language=”powershell”]
$PortTest = Test-NetConnection ex04 -Port 80 -InformationLevel Quiet
If ($PortTest) {Write-host "Server EX04 has port 80 open!" -ForegroundColor Cyan}
[/sourcecode]

Related Connection Testing

For Windows servers, we can also use a WMI or CIM connection to see if a server is reachable. Remember that if a server is on the domain, both of these methods should work. However if a server is not on the domain, It is easier to use WMI cmdlets. If there is a need to use CIM, then a new CIM session needs to be created with the ‘New-CIMSession’ cmdlet which is similar to the New-PSSession cmdlet for connecting to remote machines via PowerShell.
In order to test a connect, we can start with CIM (without using New-CIMSession) and then WMI to test whether a server is up. We can do so with code like this:
[sourcecode language=”powershell”]
# All Domain Controller
$ADServers = (Get-ADDomainController -Filter *).name
# All Exchange Servers
$ExchangeServers = (Get-ExchangeServer).Name
Function ConnectionTest ($Server,$Type) {
Try {
$ConnectionTest = Get-WmiObject -Class Win32_Service -ComputerName $Server -ErrorAction STOP
write-host "The $Type server $Server is Accessible!" -ForegroundColor Green
} Catch {
Write-host "The $Type server $Server is inaccessible!" -ForegroundColor Red
}
}
Foreach ($ADServer in $ADServers) {
$Type = "Domain Controller"
ConnectionTest $ADServer $Type
}
# Test
Foreach ($ExchangeServer in $ExchangeServers) {
$Type = "Exchange"
ConnectionTest $ExchangeServer $Type
}
[/sourcecode]
Which produces this output:

Practical PowerShell Usages?

It is one thing to test a connection, but an entirely different concept is to use that information to make a decision. For a script needing to connect to a remote computer, it would be ideal to check that server first before connecting and registering an error if the test connection fails. For a script that would need to download updates or software from the Internet, confirming access was there prior would be good as well.

How can we accomplish this?

Internet Access Test and Decision Making:
[sourcecode language=”powershell”]
$InternetAccess = (Get-NetConnectionProfile -IPv4Connectivity Internet).ipv4connectivity
If ($InternetAccess -eq "Internet") {
<perform some task here>
} Else {
Write-Host "No Internet connection could be found. Please fix and rerun this script"
}
[/sourcecode]
Server Connection Test and Decision Making
In the below code, PowerShell will first attempt to connect via CIM. If this fails, the $TryWMI variable will be set to $true and this trigger the WMI code next. If that fails, we are notified of this failure.
[sourcecode language=”powershell”]
Try {
$RAM = (Get-CIMInstance -ComputerName DC01 -ClassName WIN32_PhysicalMemory -ErrorAction STOP | Measure-Object -Property Capacity -Sum).Sum/1GB
} Catch {
$TryWMI = $True
}
If ($TryWMI) {
Try {
$RAM = (Get-WMIObject -Computer DC01 -Class WIN32_PhysicalMemory -ErrorAction STOP | Measure-Object -Property Capacity -Sum).Sum/1GB
} Catch {
Write-host "The server DC01 could not be queried" -ForegroundColor Red
}
}
[/sourcecode]

Related Post