The little example I discuss in this post shows you how you can easily monitor an HTTP port and a Windows service with PowerShell.

One of the most important tasks operations must do day in and day out is to keep those servers up. The only way to do that is through constant monitoring of the services those servers provide.

A slew of software out there can monitor and notify you for just about anything. But what if you don't need something complex? Maybe you just need a simple monitor that checks a few common things on a server every so often and sends an email when it detects a problem. One way to do that is through a PowerShell script.

To create a monitor, we need to define five things:

  • The service to monitor
  • The trigger
  • The threshold determining when to send notifications
  • The type of notification
  • The notification recipient

For this example, I'm going to monitor whether the server responds to a ping, whether a Windows service is running, and whether the server responds on the HTTP port. These monitors will trigger every time I run the script, though we could easily add this to a scheduled task. If any monitor reaches a threshold, I'll receive an email letting me know which monitor crossed the threshold.

Now that we know precisely what our monitoring script is going to do, let's get down to creating it!

We'll first have to come up with the code that will check for each of these situations. I will build each monitor to return either a True or False state indicating whether it crossed the threshold.

Ping - Test-Connection -ComputerName <ComputerName> -Quiet -Count 1 Windows service - (Get-Service -Name <ServiceName> -ComputerName <ComputerName>).Status -eq 'Running' TCP port - (Test-NetConnection  ComputerName <ComputerName> -CommonTCPPort HTTP).TcpTestSucceeded

Now that I have the code for each monitor, I'll then begin to build a reusable script that can run these checks on multiple servers at once. You can see I'm returning a PSCustomObject with the server name as a property. I'm doing this because if I'm checking multiple servers at once, I can see the server name that matches up with the properties.

## Test-Server.ps1

foreach ($name in $ServerName) {
        ServerName = $name
        PingAvailable = (Test-Connection -ComputerName $name -Quiet -Count 1)
        ServiceRunning = (Get-Service -Name 'wuauserv' -ComputerName $name).Status -eq 'Running'
        PortOpen = (Test-NetConnection -ComputerName $name -CommonTCPPort HTTP).TcpTestSucceeded

I'll then run this script, passing it a couple of server names to see what happens.

PS> .\Test-Server.ps1 -ServerName CLIENT,WEBSRV1
Output of the PowerShell monitoring script

Output of the PowerShell monitoring script

You can see now I'm getting back some useful data. Now that I've set up the monitors, I then need to send an email if one of the monitors return False. To do that, I'll add a condition to check for the value of each monitor. If one is False, only then will it send an email.

## Test-Server.ps1

foreach ($name in $ServerName) {
    $monitors = @{
        PingAvailable = { Test-Connection -ComputerName $name -Quiet -Count 1 }
        WuauServServiceRunning = { (Get-Service -Name 'wuauserv'  ComputerName $name).Status -eq 'Running' }
        HTTPOpen = { (Test-NetConnection -ComputerName $name -CommonTCPPort HTTP).TcpTestSucceeded }
        if (-not (& $_.Value)) {
            $emailParams = @{
                From = ""
                To = ''
                Subject = 'Monitor Down'
                Body = "The monitor [$($_.Key)] is down on server [$($name)]!"
                SMTPServer = 'mailserver.lab.local'
            Send-MailMessage @emailParams

You can see I got a little fancy here. Creating a hash table with each key being the monitor name and the value being a scriptblock with the action allows me to add and remove monitors easily at will. It's also a great way to list all monitors together to get a bird's eye view of everything occurring.

At this point, the script is going to be running each monitor for every server passed to the script. If the monitor returns False, it will then send an email to me.

Subscribe to 4sysops newsletter!

There are lots of ways to create simple monitors like this in PowerShell. This is only one way, but by following the same logic that I did, you can be sure to create an easy-to-use script that will quickly allow you to see the status of each of your servers.

  1. tmack (Rank: 2)
    4 years ago

    Thanks Adam. I'm now using this as a template to monitor services across my environment.

  2. PowerMe! (Rank: 3)
    4 years ago

    Nice little monitor. I guess I am missing something. Shouldn't we include a frequency for probes?

  3. Adrian 3 years ago

    @PowerMe!: That's a good question, but he mentioned that we can use this in a Scheduled Task, therefore we'll define the frequency in that, instead of the script.

Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2021


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account