Skip to content

Instantly share code, notes, and snippets.

@kiwi-cam
Last active May 31, 2024 03:36
Show Gist options
  • Save kiwi-cam/076acb39aa2dadc28ce873c5ecbf6df5 to your computer and use it in GitHub Desktop.
Save kiwi-cam/076acb39aa2dadc28ce873c5ecbf6df5 to your computer and use it in GitHub Desktop.
A simple Powershell script that monitors a remote hosts connection. Loops constantly reporting to the screen when the status changes. Optionally also records to the event log, makes an audible beep, and/or sends emails.
<#
.SYNOPSIS
Tests the connection to the supplied host or IP and reports back on changes to its status.
.DESCRIPTION
This script will check the connection to the supplied hostname or IP address every 5 second's to
monitor its status. If the status changes, a message is recorded, the Eventlog is update (optional), and an email is sent
to a supplied email address (optional).
If a TCPPort parameter is suppied the script will attempt to connect to this port. Otherwise a simple ICMP Ping is used.
To end monitoring, press CTRL-C
.PARAMETER RemoteHost
A String specifying host or IP address you'd like to monitor. You can also specify a TCPport here using host:port syntax.
.PARAMETER EmailAddress
A String specifying the email address to notify of status changes. If not supplied, or empty, emails are not sent.
In order to use this, first edit the script to supply a valid SMTP server, port, and from address.
.PARAMETER EventLog
If true, status changes are also recorded in the Windows Application EventLog.
In order to use this, first run this command at an Administrator Powershell Prompt:
> New-EventLog -LogName Application -Source MonitoringConnection
.PARAMETER NoNotify
If true, status changes will not show up as Windows notifications.
.PARAMETER Silent
If true, the script will not create any beeps as the status changes.
.PARAMETER Pause
The number of seconds to wait between tests. Default 5 seconds.
.PARAMETER TCPPort
If supplied, the script will test a connection to the supplied TCP port. If not supplied a ICMP Ping test is used.
.PARAMETER Namespace
If supplied, the script will run a query on this WMI Namespace on the supplied Host
.PARAMETER Class
If supplied, the script will run a query on this WMI Class of the supplied namespace on the supplied Host
.PARAMETER WMIProperty
The WMI Property to monitor. Any changes in value will be reported
.PARAMETER WMIFilter
The Filter used to identify the correct result in the WMI query.
.EXAMPLE
./Start-Monitoring google.com
.EXAMPLE
./Start-Monitoring -RemoteHost 8.8.8.8 -EmailAddress [email protected]
.EXAMPLE
./Start-Monitoring -RemoteHost 8.8.8.8 -EmailAddress [email protected] -EventLog $true
.EXAMPLE
./Start-Monitoring -RemoteHost 8.8.8.8 -TCPPort 53
.EXAMPLE
./Start-Monitoring -RemoteHost 8.8.8.8:53
.EXAMPLE
./Start-Monitoring -RemoteHost @("www.google.com:443","8.8.8.8:53")
.EXAMPLE
./Start-Monitoring -RemoteHost WebServer1 -Namespace "root\cimv2" -Class Win32_PerfRawData_APPPOOLCountersProvider_APPPOOLWAS -WMIProperty CurrentApplicationPoolState -WMIFilter "{$_.Name -like 'SLSS'}"
.NOTES
Version: 1.7
Author: Cameron McConnochie
Creation Date: 12 June 2020
Purpose/Change: Added support for host:port format to allow multiple host and port combos to monitor
Version: 1.6
Author: Cameron McConnochie
Creation Date: 16 Sept 2019
Purpose/Change: Added support for an array of hosts to monitor
Version: 1.5
Author: Cameron McConnochie
Creation Date: 17 June 2019
Purpose/Change: Added Core compatibility
Version: 1.4
Author: Cameron McConnochie
Creation Date: 22 March 2019
Purpose/Change: Added WMI monitoring
Version: 1.3
Author: Cameron McConnochie
Creation Date: 26 Feb 2019
Purpose/Change: Added Validation of the supplied hostname/IP
Version: 1.2
Author: Cameron McConnochie
Creation Date: 8 Oct 2018
Purpose/Change: Added Notifications
Version: 1.1
Author: Cameron McConnochie
Creation Date: 10 Aug 2018
Purpose/Change: Added TCP Port monitoring
Version: 1.0
Author: Cameron McConnochie
Creation Date: 26 July 2018
Purpose/Change: Initial script development
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[ValidateScript({
if ($_ -like "*:*") {
if($_.Split(":")[0] -As [IPAddress] -and $_.Split(":")[1] -As [Int]){
$True
}else {
if(([System.Net.Dns]::GetHostEntry($_.Split(":")[0])) -and $_.Split(":")[1] -As [Int]){
$True
}else{
Throw "$($_) is not a valid IP or hostname. Try again."
}
}
} elseif($_ -As [IPAddress]){
$True
} else {
if([System.Net.Dns]::GetHostEntry($_)){
$True
}else{
Throw "$($_) is not a valid IP or hostname. Try again."
}
}
})]
[string[]]$RemoteHost,
[Parameter(Mandatory=$False)]
[ValidateScript({
if($_ -Match "\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b" -or $_ -eq $null){
$True
} else {
Throw "$($_) is not a valid email address. Try again, or remove this parameter to skip email alerts."
}
})]
[mailaddress]$EmailAddress = $null,
[Parameter(Mandatory=$False)]
[switch]$EventLog,
[Parameter(Mandatory=$False)]
[switch]$NoNotify,
[Parameter(Mandatory=$False)]
[switch]$Silent,
[Parameter(Mandatory=$False)]
[int32]$Pause = 5,
[Parameter(Mandatory=$False,
ParameterSetName = 'Port')]
[int32]$TCPPort,
[Parameter(Mandatory=$true,
ParameterSetName = 'WMI')]
[string]$Namespace,
[Parameter(Mandatory=$true,
ParameterSetName = 'WMI')]
[string]$Class,
[Parameter(Mandatory=$true,
ParameterSetName = 'WMI')]
[string]$WMIProperty,
[Parameter(Mandatory=$False,
ParameterSetName = 'WMI')]
[scriptblock]$WMIFilter
)
######
#
# SMTP Mail Server Settings, edit these values in order to use email alerts
#
######
$SMTPServer = "smtp.someopenmailserver.com"
$SMTPPort = 25
$SMTPFromAddress = "[email protected]"
#Script Starts here...
$RemoteHostStatus = 99 #1 = online, 2 = offline, 3 = undefined
[string]$WMIPrevious = "99" #Used to identify changes
#Error Check
#Confirm EventLog Source is configured if required
if($EventLog){
try{
[System.Diagnostics.EventLog]::SourceExists("MonitoringConnection") | Out-Null
}catch{
throw "In order to record to the EventLog, first run this command at an Administrator Powershell Prompt: `n`
> New-EventLog -LogName Application -Source MonitoringConnection"
}
}
if($EmailAddress -ne $null){
if(-not ((Test-NetConnection -ComputerName $SMTPServer -Port $SMTPPort).TcpTestSucceeded)){
throw "Unable to connect to the specified SMTP server. Confirm the settings in this script and retry `n`
$($SMTPServer) unreachable on port $($SMTPPort)"
}
#Clear the progress bar
Write-Progress -Activity "Test-NetConnection - $($SMTPServer):$($SMTPPort)" -Completed
}
#Deal with an Array first
If($RemoteHost.Count -gt 1){
Write-Host "Monitoring the connection status of $($RemoteHost)" -ForegroundColor Blue
Write-Host " press CTRL-C to stop" -ForegroundColor Blue
Write-Host ""
Write-Progress -Activity "Monitoring connection status of $($RemoteHost)" -id $PID -Status "..."
# Change the default behavior of CTRL-C so that the script can intercept and use it versus just terminating the script.
[Console]::TreatControlCAsInput = $True
# Sleep for 1 second and then flush the key buffer so any previously pressed keys are discarded and the loop can monitor for the use of
# CTRL-C. The sleep command ensures the buffer flushes correctly.
Start-Sleep -Seconds 1
$Host.UI.RawUI.FlushInputBuffer()
$Jobs = @()
$ScriptPath = $MyInvocation.MyCommand.Definition
#Shared
$ScriptArgs = @{
EventLog = $EventLog
NoNotify = $NoNotify
Silent = $Silent
Pause = $Pause
}
if($EmailAddress){$ScriptArgs.Add("EmailAddress", $EmailAddress)}
#Unique
If($TCPPort){
# Port Query
if($TCPPort){$ScriptArgs.Add("TCPPort", $TCPPort)}
}elseIf($Namespace){
# WMI Query
if($Namespace){$ScriptArgs.Add("Namespace",$Namespace)}
if($Class){$ScriptArgs.Add("Class",$Class)}
if($WMIProperty){$ScriptArgs.Add("WMIProperty",$WMIProperty)}
if($WMIFilter){$ScriptArgs.Add("WMIFilter",$WMIFilter)}
}else{
# Ping Query
}
$RemoteHost | ForEach-Object {
$Jobs += Start-Job -Name "Monitor-$($_)" -ScriptBlock {param($ScriptPath, $RemoteHost, $ScriptArgs)
$ScriptArgs.Add("RemoteHost",$RemoteHost)
&$ScriptPath @ScriptArgs
} -ArgumentList @($ScriptPath, $_, $ScriptArgs)
}
While ((Get-Job | Where-Object {$_.Name -like "Monitor-*"}).Count -gt 0) {
Receive-Job -Job $Jobs
# If a key was pressed during the loop execution, check to see if it was CTRL-C (aka "3"), and if so exit the script after clearing
# out any running jobs and setting CTRL-C back to normal.
If ($Host.UI.RawUI.KeyAvailable -and ($Key = $Host.UI.RawUI.ReadKey("AllowCtrlC,NoEcho,IncludeKeyUp"))) {
If ([Int]$Key.Character -eq 3) {
Write-Host ""
Write-Warning "CTRL-C was used - Shutting down any running jobs before exiting."
Get-Job | Where-Object {$_.Name -like "Monitor-*"} | Remove-Job -Force -Confirm:$False
[Console]::TreatControlCAsInput = $False
Return
}
# Flush the key buffer again for the next loop.
$Host.UI.RawUI.FlushInputBuffer()
}
#Add a small pause to ease CPU load
Start-Sleep -Milliseconds 200
}
}
#Extract TCP Port if encoded in Host
If ($RemoteHost -like "*:*") {
$TCPPort = [Int32]$RemoteHost.Split(":")[1]
$RemoteHost = $RemoteHost.Split(":")[0]
}
If($Host.Name -ne "ServerRemoteHost"){
Write-Host "Monitoring the connection status of $($RemoteHost)" -ForegroundColor Blue
Write-Host " press CTRL-C to stop" -ForegroundColor Blue
Write-Host ""
}
#Setup Nofitications
If (-not $NoNotify){
$AppId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]
$WarningLogo = "$env:TEMP\ToastWarningLogo.png"
if (-not (Test-Path $WarningLogo)){
$Logo = "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"
[byte[]]$Bytes = [convert]::FromBase64String($Logo)
[System.IO.File]::WriteAllBytes($WarningLogo,$Bytes)
}
$InfoLogo = "$env:TEMP\ToastInfoLogo.png"
if (-not (Test-Path $InfoLogo)){
$Logo = "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"
[byte[]]$Bytes = [convert]::FromBase64String($Logo)
[System.IO.File]::WriteAllBytes($InfoLogo,$Bytes)
}
}
While ($true){
If ($TCPPort){
#This test is used to reduce the timeout - thanks to Jan Doggen: https://superuser.com/questions/805621/test-network-ports-faster-with-powershell
$tcpclient = new-Object system.Net.Sockets.TcpClient
$iar = $tcpclient.BeginConnect($RemoteHost,$TCPPort,$null,$null)
$wait = $iar.AsyncWaitHandle.WaitOne(2000,$false)
if(!$wait)
{
# Close the connection and report timeout
$tcpclient.Close()
$Result = $null
}
else
{
# Close the connection and report the error if there is one
$error.Clear()
Try{
$tcpclient.EndConnect($iar) | out-Null
}catch{}
if(!$?){
$Result = $null
}else{
$Result = "Success"
}
$tcpclient.Close()
}
$OKStatus = "listening on $($TCPPort)"
$ErStatus = "not listening on $($TCPPort)"
}elseif($WMIProperty){
if($Pause -lt 30){
Write-Host "A pause of only $($Pause) between WMI queries will strain the remote host. Adjusting to 30 seconds."
$Pause = 30
}
$WMIResult = Get-WmiObject -Namespace $Namespace -Class $Class -ComputerName $RemoteHost
if($WMIFilter){
$WMIResult = $WMIResult.Where($WMIFilter)
}
if($WMIResult.Count -gt "1"){
throw "Multiple WMI results found, check you're using a valid filter."
}elseif($WMIResult.Count -eq "0"){
$WMIResult = "NotFound"
}else{
#If a single result found, update the result to its value
$WMIResult = $WMIResult | Select-Object -ExpandProperty $WMIProperty
}
#Always return a Result of 1, just use the RemoteHostStatus variable to mark it as a different/a change.
$Result = 1
if($WMIResult -ne $WMIPrevious){
#No change, Update history value to highlight change
$RemoteHostStatus = 0
}else{
#No change, Update history value to highlight change
$RemoteHostStatus = 1
}
$WMIPrevious = $WMIResult
$ErStatus = $OKStatus = "$($WMIProperty) has status $($WMIResult)"
}else{
$Result = Test-Connection -Count 1 -ComputerName $RemoteHost -Quiet
$OKStatus = "online"
$ErStatus = "offline"
}
If($Result){
#Host is online/good
If($RemoteHostStatus -ne 1){
#New Status
Write-Host " $($RemoteHost) $($OKStatus) at $(Get-Date -Format G)" -ForegroundColor Green
If($Host.Name -ne "ServerRemoteHost"){ $Host.PrivateData.ProgressBackgroundColor='DarkCyan' }
Write-Progress -id $PID -Activity " Monitoring connection status of $($RemoteHost)" -Status (Get-Culture).TextInfo.ToTitleCase($OKStatus.ToLower())
If(-not $Silent){
[console]::beep(2000,300)
}
If(-not $NoNotify){
Write-Debug "Showing notification"
$XmlString = @("
<toast duration = 'short'>
<visual>
<binding template='ToastGeneric'>
<text>$($RemoteHost) $($OKStatus)</text>
<text>$($RemoteHost) $($OKStatus) at $(Get-Date -Format G)</text>
<image src='$InfoLogo' placement='appLogoOverride' hint-crop='circle' />
</binding>
</visual>
<audio src='ms-winsoundevent:Notification.Default' />
</toast>
")
$ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
$ToastXml.LoadXml($XmlString)
$Toast = [Windows.UI.Notifications.ToastNotification]::new($ToastXml)
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppId).Show($Toast)
}
If($EmailAddress -ne $null){
$Message = "$($RemoteHost) $($OKStatus) at $(Get-Date -Format G)"
Send-MailMessage -To $EmailAddress -Body $Message -BodyAsHtml -From $SMTPFromAddress -SmtpServer $SMTPServer -Port $SMTPPort -Subject "$($RemoteHost) $($OKStatus)"
}
If($EventLog){
Write-EventLog -LogName Application -Source MonitoringConnection -Message "$($RemoteHost) $($OKStatus)" -EventId 8000 -EntryType Information
}
$RemoteHostStatus = 1
}
}else{
#Host is offline/changed
If($RemoteHostStatus -ne 0){
#New Status
Write-Host " $($RemoteHost) $($ErStatus) at $(Get-Date -Format G)" -ForegroundColor Red
If($Host.Name -ne "ServerRemoteHost"){ $Host.PrivateData.ProgressBackgroundColor='Red' }
Write-Progress -id $PID -Activity " Monitoring connection status of $($RemoteHost)" -Status (Get-Culture).TextInfo.ToTitleCase($ErStatus.ToLower())
If(-not $Silent){
[console]::beep(500,300)
}
If($EmailAddress -ne $null){
$Message = "$($RemoteHost) $($ErStatus) at $(Get-Date -Format G)"
Send-MailMessage -To $EmailAddress -Body $Message -BodyAsHtml -From $SMTPFromAddress -SmtpServer $SMTPServer -Port $SMTPPort -Subject "$($RemoteHost) $($ErStatus)"
}
If(-not $NoNotify){
Write-Debug "Showing notification"
$XmlString = @("
<toast duration = 'short'>
<visual>
<binding template='ToastGeneric'>
<text>$($RemoteHost) $($ErStatus)</text>
<text>$($RemoteHost) $($ErStatus) at $(Get-Date -Format G)</text>
<image src='$WarningLogo' placement='appLogoOverride' hint-crop='circle' />
</binding>
</visual>
<audio src='ms-winsoundevent:Notification.Default' />
</toast>
")
$ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
$ToastXml.LoadXml($XmlString)
$Toast = [Windows.UI.Notifications.ToastNotification]::new($ToastXml)
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($AppId).Show($Toast)
}
If($EventLog){
Write-EventLog -LogName Application -Source MonitoringConnection -Message "$($RemoteHost) $($ErStatus)" -EventId 8001 -EntryType Warning
}
$RemoteHostStatus = 0
}
}
#Pause before trying again
Start-Sleep -Seconds $Pause
}
@Reazin
Copy link

Reazin commented Jun 10, 2020

Hy!
Can i use this script to somehow monitor different hosts with different ports? ex. something.ddns.net 8001 and another.ddns.net.8003
So far I can do different hosts but with the same port.

@kiwi-cam
Copy link
Author

Hi @Reazin. You can now. I've just updated the script to support the host as a host:port combination, which you can feed into an array. Using your example, this now should work:
./Start-Monitoring -RemoteHost @("something.ddns.net:8001","another.ddns.net:8003")

@Reazin
Copy link

Reazin commented Jun 12, 2020

Thanks @kiwi-cam ,I will test it on the weekend. I'm very excited about this script!

@Reazin
Copy link

Reazin commented Jun 15, 2020

Hi @kiwi-cam!
For some reason I this get error when I try to use more than one domains: Cannot validate argument on parameter 'RemoteHost'. Exception calling "GetHostEntry" with "1" argument(s):

@kiwi-cam
Copy link
Author

Can you show me how you’re running the script? I’ll try to reproduce the error here.

@Reazin
Copy link

Reazin commented Jun 15, 2020

./Start-Monitoring -RemoteHost @("example2.duckdns.net:8001","example1.duckdns.net:8003")
#I added the last line to see what kind of error it recieves
Read-Host -Prompt "Press Enter to exit"
#I tried to add the parameters while only running the script piece by piece. the same error happens.

@kiwi-cam
Copy link
Author

Hi @Reazin. What's the full error message you're getting, is it this:
Start-Monitoring: Cannot validate argument on parameter 'RemoteHost'. Exception calling "GetHostEntry" with "1" argument(s): "No such host is known."

This is expected behaviour. The script validates the arguments, including confirming that a hostname can be resolved by DNS. The error "No such host is known" just means that it can't find an IP address for the host name you supplied.

@Reazin
Copy link

Reazin commented Jun 25, 2020

Hey @kiwi-cam.
I have checked again and I made a mistake (by not adding a " at a host).
Just a little bit of help I need more. How can I exactly configure the e-mail for this? (I'm not really familiar with this).
Thanks in advance :)

@kiwi-cam
Copy link
Author

For that you need to know SMTP server settings. You'll need to put your settings into lines 171-173:

    $SMTPServer = "smtp.someopenmailserver.com"
    $SMTPPort = 25
    $SMTPFromAddress = "[email protected]"

For home, using your ISP's mail server settings are going to be the best/easiest option.

@khari14
Copy link

khari14 commented Aug 19, 2020

Unable to find type [mailaddress]: make sure that the assembly containing this type is loaded.
At D:\psftpMonitoring\Start-Monitoring.ps1:131 char:22

  •     [mailaddress] <<<< $EmailAddress = $null,
    
    • CategoryInfo : InvalidOperation: (mailaddress:String) [], ParentContainsErrorRecordException
    • FullyQualifiedErrorId : TypeNotFound

@khari14
Copy link

khari14 commented Aug 19, 2020

Hi Kiwi - I have saved the smtp server details and I am facing above error for $EmailAddress. I gave from email and port 25 as smtp port as inputs

@khari14
Copy link

khari14 commented Aug 19, 2020

I am running on server 2008 R2

@tiagoguma
Copy link

Congrats for the script! Im trying to schedule with params in win10 but it wont work. Is it possible to work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment