Windows Server Status Monitor v1.5

I wanted to create a lightweight and easy to setup server status monitor. It needed to highlight any metrics that were outside of a customisable threshold visually and be able to e-mail the report or run continuously. Based on a script from Bhavik Solanki (on TechNet) and with some help from my good friend, and software developer Dan Price, we created WinServ-Status, now known as Windows Server Status Monitor.

This utility is available to download from the Microsoft TechNet GalleryPowerShell Gallery and GitHub.

-Mike

Twitter – @Digressive

 

Features and Requirements

  • The utility will display the server name, uptime, CPU, memory and storage information, online status.
  • The utility can be configured with a customisable alerts for the CPU, memory and storage.
  • The utility can display the results as either a CSV file or a HTML file.
  • The utility can be configured to monitor continuously, or run once.
  • The utility can be configured to e-mail the results.

The utility has been tested running on Windows 10 and Windows Server 2016, monitoring PCs and Servers running Windows 10, Windows Server 2016, Windows Server 2012 R2, and Windows Server 2008 R2. The utility must be run as a user with administrator-level privileges to the systems it is monitoring.

 

Generating A Password File

The password used for SMTP server authentication must be in an encrypted text file. To generate the password file, run the following command in PowerShell, on the computer that is going to run the script and logged in with the user that will be running the script. When you run the command you will be prompted for a username and password. Enter the username and password you want to use to authenticate to your SMTP server.

Please note: This is only required if you need to authenticate to the SMTP server when send the log via e-mail.

$creds = Get-Credential
$creds.Password | ConvertFrom-SecureString | Set-Content c:\scripts\ps-script-pwd.txt

After running the commands, you will have a text file containing the encrypted password. When configuring the -Pwd switch enter the path and file name of this file.

 

Configuration

The table below shows all the command line options available with descriptions and example configurations.

Command Line Switch Mandatory Description Example
-List Yes The TXT file containing the netbios names of the servers you wish to check. C:\foo\Servers.txt
-O Yes The location to output the HTML or CSV results file. C:\foo
-CpuAlert No The minimum percentage of CPU usage that should trigger an alert. 95
-DiskAlert No The minimum percentage of any disk usage that should trigger an alert. 85
-MemAlert No The minimum percentage of memory usage that should trigger an alert. 90
-Refresh No The number of seconds the script should wait before refreshing the results.

The minimum refresh period is 300 seconds (5 minutes) and the maximum is 28800 (8 hours).

600
-Light No Configure the HTML results file to have a light theme. N/A
-Csv No Export a CSV file, instead of a HTML file. N/A
-SendTo No The email address to send the log file to. me@contoso.com
-From No* The email address that the log file should be sent from.

*This switch isn’t mandatory but is required if you wish to email the log file.

example@contoso.com
-Smtp No* SMTP server address to use for the email functionality.

*This switch isn’t mandatory but is required if you wish to email the log file.

mail01.contoso.com

OR

smtp.live.com

OR

smtp.office365.com

-User No* The username of the account to use for SMTP authentication.

*This switch isn’t mandatory but may be required depending on the configuration of the SMTP server.

example@contoso.com
-Pwd No* The location of the file containing the encrypted password of the account to use for SMTP authentication.

*This switch isn’t mandatory but may be required depending on your SMTP server.

c:\foo\ps-script-pwd.txt
-UseSsl No* Add this option if you wish to use SSL with the configured SMTP server.

Tip: If you wish to send email to outlook.com or office365.com you will need this.

*This switch isn’t mandatory but may be required depending on the configuration of the SMTP server.

N/A

 

Change Log

2018-06-10 Version 1.5

  • Added light theme for the web page.
  • Added ability to export a CSV file instead of a web page.
  • Improved the Offline visual effect on the web page.

2018-05-24 Version 1.4

  • Servers are now sorted alphabetically, regardless of how they are entered in the text file.
  • Offline servers are automatically shuffled to the top of the report.
  • Added validation for the command line parameters.
  • Removed IP addresses, and table headers to make room for more information.
  • Due to removing table headers, added component name to CPU and RAM usage columns.
  • Added new effect using css animation for offline servers.
  • Added different shade of black for alternate table rows.

2017-10-16 Version 1.3

  • Changed SMTP authentication to require an encrypted password file.
  • Added instructions on how to generate an encrypted password file.

2017-10-09 Version 1.2

  • Added necessary information to add the script to the PowerShell Gallery.

2018-09-27 Version 1.1

  • Added capability for the script to run and monitor server status continuously.
  • Added icons to warning and error states to assist in at-a-glace reporting.
  • Added memory and CPU usage.
  • Added warning thresholds for memory and CPU usage.
  • Changed disk usage reporting from “percent free” to actual disk usage to match the added CPU and memory usage.
  • Changed the warning threshold to of disk usage to match the change.
  • Changed the visual style of the report.
  • Changed visual style of warnings and errors.
  • Changed code formatting for readability.

2017-07-28 Version 1.0

  • First public release.

 

PowerShell Code


<#PSScriptInfo .VERSION 1.5 .GUID 2cb94e4f-1e85-4712-9441-91abcaea8572 .AUTHOR Mike Galvin twitter.com/digressive & Dan Price twitter.com/therezin, based on code by Bhavik Solanki. .COMPANYNAME .COPYRIGHT (C) Mike Galvin. All rights reserved. .TAGS Windows Server Status Report Monitor .LICENSEURI .PROJECTURI https://gal.vin/2017/07/28/windows-server-status/ .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #>

<# .SYNOPSIS Creates a status report of Windows Servers. .DESCRIPTION Creates a status report of Windows Servers. This script will: Generate a HTML status report from a configurable list of Windows servers. The report will highlight information is the alert threashold is exceeded. Please note: to send a log file using ssl and an SMTP password you must generate an encrypted password file. The password file is unique to both the user and machine. The command is as follows: $creds = Get-Credential $creds.Password | ConvertFrom-SecureString | Set-Content c:\foo\ps-script-pwd.txt .PARAMETER List The path to a text file with a list of server names to monitor. .PARAMETER O The path where the HTML report should be output to. The filename will be WinServ-Status-Report.htm. .PARAMETER DiskAlert The percentage of disk usage that should cause the disk space alert to be raised. .PARAMETER CpuAlert The percentage of CPU usage that should cause the CPU alert to be raised. .PARAMETER MemAlert The percentage of memory usage that should cause the memory alert to be raised. .PARAMETER Refresh The number of seconds that she script should wait before running again. The minimum is 300 seconds (5 minutes) and the maximum is 28800 (8 hours). If not configured the script will run once and then exit. .PARAMETER Light Use a light theme for the web page generated. .PARAMETER Csv The path where the CSV file of the report should be output to. The filename will be WinServ-Status-Report.csv. .PARAMETER SendTo The e-mail address the log should be sent to. .PARAMETER From The from address the log should be sent from. .PARAMETER Smtp The DNS or IP address of the SMTP server. .PARAMETER User The user account to connect to the SMTP server. .PARAMETER Pwd The txt file containing the encrypted password for the user account. .PARAMETER UseSsl Connect to the SMTP server using SSL. .EXAMPLE WinServ-Status.ps1 -List C:\foo\servers.txt -O C:\foo -DiskAlert 90 -CpuAlert 95 -MemAlert 85 -Refresh 300 -Light -Csv The script will execute using the list of servers and output a html report called WinServ-Status-Report.htm to C:\foo. The disk usage alert will highlight at 90% usage for any one drive, the CPU usage alert will highlight at 95% usage, and the memory usage alert will highlight at 85% usage. The status of the servers will refresh every 5 minutes, and the web page will have a light theme instead of a dark theme. In addition to the HTML file, a CSV report will also be generated. #>

## Set up command line switches and what variables they map to
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True)]
    [Alias("List")]
    [ValidateScript({Test-Path -Path $_ -PathType Leaf})]
    [string]$ServerFile,
    [Parameter(Mandatory=$True)]
    [Alias("O")]
    [ValidateScript({Test-Path $_ -PathType 'Container'})]
    [string]$OutputPath,
    [Alias("DiskAlert")]
    [ValidateRange(0,100)]
    [int]$DiskAlertThreshold,
    [Alias("CpuAlert")]
    [ValidateRange(0,100)]
    [int]$CpuAlertThreshold,
    [Alias("MemAlert")]
    [ValidateRange(0,100)]
    [int]$MemAlertThreshold,
    [Alias("Refresh")]
    [ValidateRange(300,28800)]
    [int]$RefreshTime,
    [switch]$Light,
    [switch]$Csv,
    [Alias("SendTo")]
    [string]$MailTo,
    [Alias("From")]
    [string]$MailFrom,
    [Alias("Smtp")]
    [string]$SmtpServer,
    [Alias("User")]
    [string]$SmtpUser,
    [Alias("Pwd")]
    [string]$SmtpPwd,
    [switch]$UseSsl)

## Function to get the up time from the server
Function Get-UpTime
{
    param([string] $LastBootTime)
    $Uptime = (Get-Date) - [System.Management.ManagementDateTimeconverter]::ToDateTime($LastBootTime)
    "$($Uptime.Days) days $($Uptime.Hours)h $($Uptime.Minutes)m"
}

## Begining of the loop. At the bottom of the script the loop is broken if the refresh option is not configured.
Do
{
    ## Setting the location of the report output.
    If ($Csv)
    {
        $OutputFile = "$OutputPath\WinServ-Status-Report.csv"
        
        ## If the CSV file already exists, clear it
        $CsvT = Test-Path -Path $OutputFile

        If ($CsvT)
        {
            Clear-Content -Path $OutputFile
        }
    }

    Else
    {
        $OutputFile = "$OutputPath\WinServ-Status-Report.htm"
    }

    $ServerList = Get-Content $ServerFile
    $Result = @()

    ## Settings colours used in HTML report
    $Green = "00e600"
    $Grey = "e6e6e6"
    $Red = "ff4d4d"
    $Yellow = "ffff4d"
    $Black = "1a1a1a"

    ## Sort Servers based on whther they are online or offline
    $ServerList = $ServerList | Sort-Object

    ForEach ($ServerName in $ServerList)
    {
        $PingStatus = Test-Connection -ComputerName $ServerName -Count 1 -Quiet

        If ($PingStatus -eq $False)
        {
            $ServersOffline += @($ServerName)
        }

        Else
        {
            $ServersOnline += @($ServerName)
        }
    }

    $ServerListFinal = $ServersOffline + $ServersOnline

    ## Look through the servers in the file provided
    ForEach ($ServerName in $ServerListFinal)
    {
        $PingStatus = Test-Connection -ComputerName $ServerName -Count 1 -Quiet

        ## If server responds, get uptime and disk info
        If ($PingStatus)
        {
            $CpuAlert = $false
            $MemAlert = $false
            $DiskAlert = $false
            $OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ServerName
            $CpuUsage = Get-WmiObject Win32_Processor -Computername $ServerName | Measure-Object -Property LoadPercentage -Average | ForEach-Object {$_.Average; If($_.Average -ge $CpuAlertThreshold){$CpuAlert = $True}; "%"}
            $Uptime = Get-Uptime($OperatingSystem.LastBootUpTime)
            $MemUsage = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ServerName | ForEach-Object {“{0:N0}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory) * 100)/ $_.TotalVisibleMemorySize); If((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory) * 100)/ $_.TotalVisibleMemorySize -ge $MemAlertThreshold){$MemAlert = $True}; "%"}
            $DiskUsage = Get-WmiObject Win32_LogicalDisk -ComputerName $ServerName | Where-Object {$_.DriveType -eq 3} | Foreach-Object {$_.DeviceID, [Math]::Round((($_.Size - $_.FreeSpace) * 100)/ $_.Size); If([Math]::Round((($_.Size - $_.FreeSpace) * 100)/ $_.Size) -ge $DiskAlertThreshold){$DiskAlert = $True}; "%"}
	    }
	
        ## Put the results together
        $Result += New-Object PSObject -Property @{
	        ServerName = $ServerName
		    Status = $PingStatus
            CpuUsage = $CpuUsage
            CpuAlert = $CpuAlert
		    Uptime = $Uptime
            MemUsage = $MemUsage
            MemAlert = $MemAlert
            DiskUsage = $DiskUsage
            DiskAlert = $DiskAlert
	    }

        ## Clear the variables after obtaining and storing the results, otherwise hilarity ensues.
        If ($ServerListFinal)
        {
            Clear-Variable ServerListFinal
        }

        If ($ServersOffline)
        {
            Clear-Variable ServersOffline
        }

        If ($ServersOnline)
        {
            Clear-Variable ServersOnline
        }

        If ($PingStatus)
        {
            Clear-Variable PingStatus
        }

        If ($CpuUsage)
        {
            Clear-Variable CpuUsage
        }

        If ($Uptime)
        {
            Clear-Variable Uptime
        }

        If ($MemUsage)
        {
            Clear-Variable MemUsage
        }

        If ($DiskUsage)
        {
            Clear-Variable DiskUsage
        }
    }

    ## If there is a result put the report together.
    If ($Result -ne $null)
    {
        ## If CSV report is specified, output a CSV file.
        If ($Csv)
        {
            ForEach($Entry in $Result)
            {
                If ($Entry.Status -eq $True)
                {
                    Add-Content -Path "$OutputFile" -Value "$($Entry.ServerName),Online,CPU: $($Entry.CpuUsage),RAM: $($Entry.MemUsage),$($Entry.DiskUsage),$($Entry.Uptime)"
                }

                Else
                {
                    Add-Content -Path "$OutputFile" -Value "$($Entry.ServerName),Offline"
                }
            }
        }

        ## If a CSV report is not specified, output a HTML file
        Else
        {
            If ($Light)
            {
## HTML Code goes here! HTML doesn't format properly with PowerShell on WordPress.
Download the script from TechNet or the PowerShell Gallery to see the complete code!
            }

            ## Output the HTML file
            $HTML | Out-File $OutputFile
        }

        ## If email was configured, set the variables for the email subject and body
        If ($SmtpServer)
        {
            $MailSubject = "Server Status Report"
            $MailBody = Get-Content -Path $OutputFile | Out-String

            ## If an email password was configured, create a variable with the username and password
            If ($SmtpPwd)
            {
                $SmtpPwdEncrypt = Get-Content $SmtpPwd | ConvertTo-SecureString
                $SmtpCreds = New-Object System.Management.Automation.PSCredential -ArgumentList ($SmtpUser, $SmtpPwdEncrypt)

                ## If ssl was configured, send the email with ssl
                If ($UseSsl)
                {
                    Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -Body $MailBody -BodyAsHtml -SmtpServer $SmtpServer -UseSsl -Credential $SmtpCreds
                }

                ## If ssl wasn't configured, send the email without ssl
                Else
                {
                    Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -Body $MailBody -BodyAsHtml -SmtpServer $SmtpServer -Credential $SmtpCreds
                }
            }

            ## If an email username and password were not configured, send the email without authentication
            Else
            {
                Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -Body $MailBody -BodyAsHtml -SmtpServer $SmtpServer
            }
        }

        ## If the refresh time option is configured, wait the specifed number of seconds then loop.
        If ($RefreshTime -ne 0)
        {
            Start-Sleep -Seconds $RefreshTime
        }
    }
}

## If the refresh time option is not configured, stop the loop.
Until ($RefreshTime -eq 0)

## End

 

18 Comments Add yours

  1. Meer says:

    Hi Mike .. really nice script …just have one question here ..how can i schedule this script to run every 8 hour

    Like

    1. Mike Galvin says:

      Hi Meer,

      Please disregard my previous reply, I was under the impression you were asking about the Hyper-V-Backup script.

      For the WinServStatus script to refresh every 8 hours, you should be able to set the refresh option to -Refresh 28800

      -Mike

      Like

  2. Senthil Rajna says:

    Hi Mike, while I run the script I can see the output has Offline, do I missing anything?

    Like

    1. Mike Galvin says:

      Hi Senthil,

      You might need to check your account privileges, or it could be the network access on the computer running the script, and if it has access to the servers in the list to check. Without more info, it can be difficult to be sure

      -Mike

      Like

  3. Jeferson says:

    Amazing script thank you so much . I don’t know if possible but I would like save too into a csv or txt file . Thank you

    Like

    1. Mike Galvin says:

      Hi Jeferson,

      Thank you for the kind words, I’m glad you like it. I’m sure it’s possible to export the info into a CSV or TXT file with some changes, however it’s not something I’m looking into right now. I’m happy for anyone to take the code and change it for their needs though.

      -Mike

      Like

  4. Prabhakar says:

    hi Mike,

    Thanks for sharing script i have run the script in power shell but showing serverfile & output path in powershell . please guide how & where to add entry serverfile & outputpath in power shell.
    PS C:\foo> C:\foo\WinServ-Status.ps1
    cmdlet WinServ-Status.ps1 at command pipeline position 1
    Supply values for the following parameters:
    ServerFile: c:\foo\servers.txt
    OutputPath: c:\foo

    Like

    1. Mike Galvin says:

      Hi Parbhakar,

      Apologies for the late reply, I only just noticed this comment. To run the monitor, you’ll need to run this command with the path to your own files:

      PowerShell -ExecutionPolicy Bypass -File [PATH-TO-SCRIPT]WinServ-Status.ps1 -List [PATH-TO-SERVER-LIST]servers.txt -O [PATH-TO-OUTPUT-FILE -DiskAlert 90 -CpuAlert 95 -MemAlert 95

      -Mike

      Like

  5. Jasper says:

    Hi Mike,

    Really like the script, nice job! I was wondering though, how could I go about adding a ‘description’ column in the output for each of the servers that are imported through the .txt file? Like it would be really nice if next to each $ServerName in the output it could have a column next to it saying what that server is being used for. (Example Output: Svrhostname1 | Main Apache Server | CPU usage | Ram Usage | etc. the rest of the already existing columns). This would be regardless if the server was up or down. Any assistance or suggestions would be greatly appreciated.

    Like

    1. Mike Galvin says:

      Hi Jasper,

      Thanks for the kind words, I’m glad the script has been useful to you. To add a description of the servers would require some work to the script. Currently it take the names of the servers in a simple TXT file and then generates all the displayed information from that. To display a user added description could be done with using a CSV file of server names along with a second field of descriptions and then the script would display the name, description and then all the other information.

      Another way of doing it would be to have the descriptions of the servers in the Computer description field in the Computer Name section of the System Info and then get that from WMI, if it’s available there.

      So there’s two ways of doing it that I can think of. I like the idea of doing it, I may add this as an option to a future version of the script when I get time to work on them again.

      Thanks for the comment.

      -Mike

      Like

  6. Phil says:

    I love the script and what it can do. Is there a way to display not only the servername but also a description. So if in the txt file I have server abc123 – Application Server. Is there a way that I can get the output to html to also display server abc123 – Application Server. This way when others look at the results they know what each server does.

    Like

    1. Mike Galvin says:

      Hi Phil,

      It is possible and something I might look into if I find the time. Essentially I’ll just need to add in an additional column and turn the servers.txt file into a .csv so it can have the description field.

      -Mike

      Like

  7. Madhukar says:

    Hello Mike ,
    i unable to run script proper i unbale to receive report on email
    please help me for the same.

    Thanks,
    MMadhukar

    Like

    1. Mike Galvin says:

      Hi Madhukar,

      I’m happy to help you but can you be more specific as to the problem you are having?

      -Mike

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.