PowerShell: Windows Server Status Report Generator

I wanted to create a script to generate a status report of a list of servers. In this report I wanted whether they were up or down, free disk space, and up time. I also wanted to highlight any problems visually and be able to e-mail the report. Based on a script from Bhavik Solanki (on TechNet) and with some help from my good friend, and .Net developer Dan Price, we created WinServ-Status.

This script is available to download from the Microsoft TechNet Script Center.

In this example, the disk alert threshold was set to 50%, so the vs01 server is highlighted as one of it’s disks is below 50% and the mail01 server is highlighted because it has not responded to a ping.

Overview

You can configure this script to do the following:

  • Get the up/down status of a list of Windows based servers.
  • Get the remaining disk space percentage, and highlight those below a threshold.
  • E-mail the report to a local or remote e-mail provider.

Compatibility and Requirements

The script has been tested running on Windows 10 & Windows Server 2016 getting status from PCs and Servers running Windows 10, Windows Server 2016, Windows Server 2012 R2, and Windows Server 2008 R2.

The PowerShell -file Parameter

When running the script via Schedule Tasks or the command prompt be sure to use the -file parameter before specifying the script, so you can use “double quotes” for the options that need them, if you do not use -file, then you should use ‘single quotes’.

Command Line Options

Here are the command line options available to you, with some examples of how to use them.

Command Line Switch Mandatory Description Example
-list Yes The text file with the servers you wish to check. C:\foo\ServerList.txt
-o Yes The location to store the HTML file. C:\foo
-alert No The percentage alert threshold for disk space. 10
-sendto No The email address to send the report to. me@contoso.com
-from No* The email address that the report should be sent from.

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

Server-Status@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 report.

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 password of the account to use for SMTP authentication.

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

P@ssw0rd
-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

 

The Complete Script

# ----------------------------------------------------------------------------
# Script: WinServ-Status_v1-0.ps1
# Version: 1.0
# Author: Mike Galvin twitter.com/digressive & Dan Price twitter.com/therezin
# Based on code by Bhavik Solanki
# Date: 28/07/2017
# ----------------------------------------------------------------------------


## Set up command line switches and what variables they map to
Param(
    [parameter(Mandatory=$True)]
    [alias("list")]
    $ServerFile,
    [parameter(Mandatory=$True)]
    [alias("o")]
    $OutputPath,
    [alias("alert")]
    $DiskAlertThreshold,
    [alias("sendto")]
    $MailTo,
    [alias("from")]
    $MailFrom,
    [alias("smtp")]
    $smtpServer,
    [alias("user")]
    $smtpUser,
    [alias("pwd")]
    $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"
}

## Change value of the following parameter as needed
$OutputFile = "$OutputPath\WinServ-Status-Report.htm"
$ServerList = Get-Content $ServerFile
$Result = @()

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

    ## If server responds, get uptime and disk info
    If ($PingStatus) {
        $OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ServerName
        $DiskAlert = $False
        $Uptime = Get-Uptime($OperatingSystem.LastBootUpTime)
        $Disk = Get-WmiObject Win32_LogicalDisk -ComputerName $ServerName | Where-Object {$_.DriveType -eq 3} | Foreach-Object {$_.DeviceID, [Math]::Round(($_.FreeSpace / $_.Size) * 100); If([Math]::Round(($_.FreeSpace / $_.Size) * 100) -ilt $DiskAlertThreshold){$DiskAlert = $True}; "%"}
        $IPv4Address = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ServerName | Select-Object -Expand IPAddress | Where-Object { ([Net.IPAddress]$_).AddressFamily -eq "InterNetwork" }
	}
	
    ## Put the results together
    $Result += New-Object PSObject -Property @{
	    ServerName = $ServerName
		IPV4Address = $IPv4Address
		Status = $PingStatus
		Uptime = $Uptime
        DiskFree = $Disk
        DiskAlert = $DiskAlert
	}

## Clear the variables after obtaining and storing the results so offline servers don't have duplicate info.
Clear-Variable IPv4Address
Clear-Variable Uptime
Clear-Variable Disk

}

## If there is a result put the HTML file together.
If ($Result -ne $null) {

The HTML got mangled by WordPress, so here’s a screenshot of the HTML code. You can download the script from TechNet – link at the top of the post.

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

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

            ## If an email password was configured, create a variable with the username and password
            If ($smtpPwd) {
                $smtpCreds = New-Object System.Management.Automation.PSCredential -ArgumentList $smtpUser, $($smtpPwd | ConvertTo-SecureString -AsPlainText -Force)

                ## 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
        }
    }
}

## End

Change Log

28/07/2017 1.0

  • First public release.

I hope you find this useful. If you’d like to get in touch with me please leave a comment or tweet me.

-Mike

Follow Mike on Twitter: @Digressive

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s