PowerShell: Disk Space Utilization HTML Report
Abstract
Monitoring disk space utilization of server(s) is a critical and important job for any administrator. Keeping things organized might improve application availability and server availability.This article takes us through the in-detail steps to read servers from a text file and validate the disk based on default/custom threshold values. The output is integrated with HTML tags. You'll basically feed a list of servers to watch over, and it will report back on these for you, meaning you could also use it as a more general "daily server disk space report"
Introduction
This post explains how to monitor DiskSpace of a group of listed servers. The threshold values are set the globally. The values can also be customized as per your requirement. The function Get-DiskSpaceReport comprises of various cmdLets and function to monitor disk drives.
- Querying Get-Win32LogicalDisks
- Use default or custom threshold values for all the listed servers
- Prepare CSS HTML document
- Validate the Freespace with reference to the disk threshold value and set the background color
- Email Address validation
- HTML Output
You can customize it as per your requirement.
The Function Get-DiskSpaceReport has six input parameters:-
- ComputerList – List of Servers – Path of an input file where servers are listed
- Warning – Warning Threshold – Default = 25%
- Critical – Critical Threshold – Default =15%
- SMTPMail – SMTP mail address
- FromID – Valid Email ID
- ToID – Valid Email ID
Examples
Example 1:- Execute with default threshold values. By default, the threshold is set to 25(Warning) and 15(Critical)
PS:\>Get-DiskSpaceReport -ComputerList c:\computer.txt -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
Example 2:- Customize the default threshold values
PS:\>Get-DiskSpaceReport -ComputerList c:\computer.txt -warning 15 -critical 10 -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
Example 3: Multiple recipients
Get-DiskSpaceReport -ComputerList c:\computer.txt -warning 25 -critical 15 -To "pjayaram@Appvion.com,prashanth.jayaram@cognizant.com" -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
Code In Detail
Output filename
The below code defines the output file location and filename. Change the location or filename as per your requirement.
$filename= "c:\freespace.htm"
New-Item -ItemType file $freeSpaceFileName -Force
The ***New-item ***cmdlet creates an item.
-Force
Forces this cmdlet to create an item that writes over an existing read-only item. Implementation varies from provider to provider. For more information, see about_Providers . Even using the Force parameter, the cmdlet cannot override security restrictions.
Prepare HTML file using CSS
The ***Add-Content ***cmdlet is used to prepare CSS HTML file. The cmdlet is to append the data to a text file. In this case, it's going to be an HTML file.
There are two ways of preparing HTML output. One is through ConvertTo-HTML and using cssri parameter which accepts style sheet path as its input and another one is through manually defining the CSS tags and building an HTML file. It's like building an HTML file with values and tags to be displayed in a file. If one has a little bit of knowledge over CSS will help a lot in this case.
The below code has modularized for simple understanding and easy to enhance the code if one has to make any changes to a template.
Code
Code with Email Validation and a single recipient
<#
.SYNOPSIS
Name : Disk Space Utilizaiton Report
Description : Get disk space usage informations from remote server(s) with WMI and output HTML file
Author : Prashanth Jayaram
* Select list of servers from a text file
* Use default or custom threshold values - common attribute set for all the servers
* Get remote Servers informations with WMI and Powershell :
* Disk (Disk type, letter, capacity in GB, free space in GB, % free , Status)
* Email validation
* HTML Output
.INPUT
.csv file with servers to activate
.OUTPUTS
Console outputs : You can alter the code to write the data to file or console
.NOTES
Version: 1.0
Author: Prashanth Jayaram
Creation Date: 2016-26-09
Purpose/Change: Initial script development
.EXAMPLE 1 - Using Default threshold values
Get-DiskSpaceReport -ComputerList c:\computer.txt -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
.EXAMPLE 2 - Setting threshold values
PS:\>Get-DiskSpaceReport -ComputerList c:\computer.txt -warning 15 -critical 10 -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
#>
Function Get-DiskSpaceReport
{
param(
[parameter(Mandatory=$True,position=0,HelpMessage="Please specify valid text file path consists of list of server")]
[Alias("MachineName")]
[string[]]$ComputerList,
[int]$warning,
[int]$critical,
[parameter(Mandatory=$true][string]$EmailTo,
[parameter(Mandatory=$true][string]$EmailFrom,
[parameter(Mandatory=$true][string]$SMTPMail
)
$script:list = $ComputerList
$freeSpaceFileName = "C:\FreeSpace.htm"
if ($Warning -eq "$NULL")
{
$Warning=25
}
if ($critical -eq "$NULL")
{
$critical=15
}
$critical = $critical
$warning = $warning
New-Item -ItemType file $freeSpaceFileName -Force
# Getting the freespace info using WMI
#Get-WmiObject win32_logicaldisk | Where-Object {$_.drivetype -eq 3 -OR $_.drivetype -eq 2 } | format-table DeviceID, VolumeName,status,Size,FreeSpace | Out-File FreeSpace.txt
# Function to write the HTML Header to the file
Function writeHtmlHeader
{
param($fileName)
$date = ( get-date ).ToString('yyyy/MM/dd')
Add-Content $fileName "<html>"
Add-Content $fileName "<head>"
Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $fileName '<title>DiskSpace Report</title>'
add-content $fileName '<STYLE TYPE="text/css">'
add-content $fileName "<!--"
add-content $fileName "td {"
add-content $fileName "font-family: Tahoma;"
add-content $fileName "font-size: 11px;"
add-content $fileName "border-top: 1px solid #999999;"
add-content $fileName "border-right: 1px solid #999999;"
add-content $fileName "border-bottom: 1px solid #999999;"
add-content $fileName "border-left: 1px solid #999999;"
add-content $fileName "padding-top: 0px;"
add-content $fileName "padding-right: 0px;"
add-content $fileName "padding-bottom: 0px;"
add-content $fileName "padding-left: 0px;"
add-content $fileName "}"
add-content $fileName "body {"
add-content $fileName "margin-left: 5px;"
add-content $fileName "margin-top: 5px;"
add-content $fileName "margin-right: 0px;"
add-content $fileName "margin-bottom: 10px;"
add-content $fileName ""
add-content $fileName "table {"
add-content $fileName "border: thin solid #000000;"
add-content $fileName "}"
add-content $fileName "-->"
add-content $fileName "</style>"
Add-Content $fileName "</head>"
Add-Content $fileName "<body>"
add-content $fileName "<table width='100%'>"
add-content $fileName "<tr bgcolor='#CCCCCC'>"
add-content $fileName "<td colspan='7' height='25' align='center'>"
add-content $fileName "<font face='tahoma' color='#003399' size='4'><strong>DiskSpace Report - $date</strong></font>"
add-content $fileName "</td>"
add-content $fileName "</tr>"
add-content $fileName "</table>"
}
# Function to write the HTML Header to the file
Function writeTableHeader
{
param($fileName)
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='10%' align='center'>Drive</td>"
Add-Content $fileName "<td width='50%' align='center'>Drive Label</td>"
Add-Content $fileName "<td width='10%' align='center'>Total Capacity(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Used Capacity(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Free Space(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Freespace %</td>"
Add-Content $fileName "</tr>"
}
Function writeHtmlFooter
{
param($fileName)
Add-Content $fileName "</body>"
Add-Content $fileName "</html>"
}
Function writeDiskInfo
{
param($fileName,$devId,$volName,$frSpace,$totSpace)
$totSpace=[math]::Round(($totSpace/1073741824),2)
$frSpace=[Math]::Round(($frSpace/1073741824),2)
$usedSpace = $totSpace - $frspace
$usedSpace=[Math]::Round($usedSpace,2)
$freePercent = ($frspace/$totSpace)*100
$freePercent = [Math]::Round($freePercent,0)
if ($freePercent -gt $warning)
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td>$freePercent</td>"
Add-Content $fileName "</tr>"
}
elseif ($freePercent -le $critical)
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td bgcolor='#FF0000' align=center>$freePercent</td>"
#<td bgcolor='#FF0000' align=center>
Add-Content $fileName "</tr>"
}
else
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td bgcolor='#FBB917' align=center>$freePercent</td>"
# #FBB917
Add-Content $fileName "</tr>"
}
}
writeHtmlHeader $freeSpaceFileName
foreach ($server in Get-Content $script:list)
{
if(Test-Connection -ComputerName $server -Count 1 -ea 0) {
Add-Content $freeSpaceFileName "<table width='100%'><tbody>"
Add-Content $freeSpaceFileName "<tr bgcolor='#CCCCCC'>"
Add-Content $freeSpaceFileName "<td width='100%' align='center' colSpan=6><font face='tahoma' color='#003399' size='2'><strong> $server </strong></font></td>"
Add-Content $freeSpaceFileName "</tr>"
writeTableHeader $freeSpaceFileName
$dp = Get-WmiObject win32_logicaldisk -ComputerName $server | Where-Object {$_.drivetype -eq 3 }
foreach ($item in $dp)
{
Write-Host $item.DeviceID $item.VolumeName $item.FreeSpace $item.Size
writeDiskInfo $freeSpaceFileName $item.DeviceID $item.VolumeName $item.FreeSpace $item.Size
}
}
Add-Content $freeSpaceFileName "</table>"
}
writeHtmlFooter $freeSpaceFileName
Function sendEmail
{
param($from,$to,$subject,$smtphost,$htmlFileName)
[string]$receipients="$to"
$body = Get-Content $htmlFileName
$body = New-Object System.Net.Mail.MailMessage $from, $receipients, $subject, $body
$body.isBodyhtml = $true
$smtpServer = $MailServer
$smtp = new-object Net.Mail.SmtpClient($smtphost)
$validfrom= Validate-IsEmail $from
if($validfrom -eq $TRUE)
{
$validTo= Validate-IsEmail $to
if($validTo -eq $TRUE)
{
$smtp.Send($body)
write-output "Email Sent!!"
}
}
else
{
write-output "Invalid entries, Try again!!"
}
}
# Email our report out
function Validate-IsEmail ([string]$Email)
{
return $Email -match "^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$"
}
$date = ( get-date ).ToString('yyyy/MM/dd')
sendEmail -from $From -to $to -subject "Disk Space Report - $Date" -smtphost $SMTPMail -htmlfilename $freeSpaceFileName
}
Code for Multiple recipients with no email validation
<#
.SYNOPSIS
Name : Disk Space Utilizaton Report
Description : Get disk space usage information from remote server(s) with WMI and output HTML file
Author : Prashanth Jayaram
* Select list of servers from a text file
* Use default or custom threshold values - common attribute set for all the servers
* Get remote Servers information with WMI and PowerShell :
* Disk (Disk type, letter, capacity in GB, free space in GB, % free , Status)
* Email validation
* HTML Output
.INPUT
.csv file with servers to activate
.OUTPUTS
Console outputs : You can alter the code to write the data to file or console
.NOTES
Version: 1.0
Author: Prashanth Jayaram
Creation Date: 2016-26-09
Purpose/Change: Initial script development
.EXAMPLE 1 - Using Default threshold values
Get-DiskSpaceReport -ComputerList c:\computer.txt -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
.EXAMPLE 2 - Setting threshold values
PS:\>Get-DiskSpaceReport -ComputerList c:\computer.txt -warning 15 -critical 10 -To pjayaram@Appvion.com -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
.EXAMPLE 3 - multiple receipients
PS:\>Get-DiskSpaceReport -ComputerList c:\computer.txt -warning 15 -critical 10 -To "pjayaram@Appvion.com,abc@appvion.com" -From pjayaram@appvion.com -SMTPMail qqma01.ppp.com
#>
Function Get-DiskSpaceReport
{
param(
[parameter(Mandatory=$True,position=0,HelpMessage="Please specify valid text file path consists of list of server")]
[Alias("MachineName")]
[string[]]$ComputerList,
[int]$warning,
[int]$critical,
[parameter(Mandatory=$true)][string]$EmailTo,
[parameter(Mandatory=$true)][string]$EmailFrom,
[parameter(Mandatory=$true)][string]$SMTPMail
)
$script:list = $ComputerList
$freeSpaceFileName = "C:\FreeSpace.htm"
if ($Warning -eq "$NULL")
{
$Warning=25
}
if ($critical -eq "$NULL")
{
$critical=15
}
$critical = $critical
$warning = $warning
New-Item -ItemType file $freeSpaceFileName -Force
# Getting the freespace info using WMI
#Get-WmiObject win32_logicaldisk | Where-Object {$_.drivetype -eq 3 -OR $_.drivetype -eq 2 } | format-table DeviceID, VolumeName,status,Size,FreeSpace | Out-File FreeSpace.txt
# Function to write the HTML Header to the file
Function writeHtmlHeader
{
param($fileName)
$date = ( get-date ).ToString('yyyy/MM/dd')
Add-Content $fileName "<html>"
Add-Content $fileName "<head>"
Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>"
Add-Content $fileName '<title>DiskSpace Report</title>'
add-content $fileName '<STYLE TYPE="text/css">'
add-content $fileName "<!--"
add-content $fileName "td {"
add-content $fileName "font-family: Tahoma;"
add-content $fileName "font-size: 11px;"
add-content $fileName "border-top: 1px solid #999999;"
add-content $fileName "border-right: 1px solid #999999;"
add-content $fileName "border-bottom: 1px solid #999999;"
add-content $fileName "border-left: 1px solid #999999;"
add-content $fileName "padding-top: 0px;"
add-content $fileName "padding-right: 0px;"
add-content $fileName "padding-bottom: 0px;"
add-content $fileName "padding-left: 0px;"
add-content $fileName "}"
add-content $fileName "body {"
add-content $fileName "margin-left: 5px;"
add-content $fileName "margin-top: 5px;"
add-content $fileName "margin-right: 0px;"
add-content $fileName "margin-bottom: 10px;"
add-content $fileName ""
add-content $fileName "table {"
add-content $fileName "border: thin solid #000000;"
add-content $fileName "}"
add-content $fileName "-->"
add-content $fileName "</style>"
Add-Content $fileName "</head>"
Add-Content $fileName "<body>"
add-content $fileName "<table width='100%'>"
add-content $fileName "<tr bgcolor='#CCCCCC'>"
add-content $fileName "<td colspan='7' height='25' align='center'>"
add-content $fileName "<font face='tahoma' color='#003399' size='4'><strong>DiskSpace Report - $date</strong></font>"
add-content $fileName "</td>"
add-content $fileName "</tr>"
add-content $fileName "</table>"
}
# Function to write the HTML Header to the file
Function writeTableHeader
{
param($fileName)
Add-Content $fileName "<tr bgcolor=#CCCCCC>"
Add-Content $fileName "<td width='10%' align='center'>Drive</td>"
Add-Content $fileName "<td width='50%' align='center'>Drive Label</td>"
Add-Content $fileName "<td width='10%' align='center'>Total Capacity(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Used Capacity(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Free Space(GB)</td>"
Add-Content $fileName "<td width='10%' align='center'>Freespace %</td>"
Add-Content $fileName "</tr>"
}
Function writeHtmlFooter
{
param($fileName)
Add-Content $fileName "</body>"
Add-Content $fileName "</html>"
}
Function writeDiskInfo
{
param($fileName,$devId,$volName,$frSpace,$totSpace)
$totSpace=[math]::Round(($totSpace/1073741824),2)
$frSpace=[Math]::Round(($frSpace/1073741824),2)
$usedSpace = $totSpace - $frspace
$usedSpace=[Math]::Round($usedSpace,2)
$freePercent = ($frspace/$totSpace)*100
$freePercent = [Math]::Round($freePercent,0)
if ($freePercent -gt $warning)
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td>$freePercent</td>"
Add-Content $fileName "</tr>"
}
elseif ($freePercent -le $critical)
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td bgcolor='#FF0000'>$freePercent</td>"
#<td bgcolor='#FF0000' align=center>
Add-Content $fileName "</tr>"
}
else
{
Add-Content $fileName "<tr>"
Add-Content $fileName "<td>$devid</td>"
Add-Content $fileName "<td>$volName</td>"
Add-Content $fileName "<td>$totSpace</td>"
Add-Content $fileName "<td>$usedSpace</td>"
Add-Content $fileName "<td>$frSpace</td>"
Add-Content $fileName "<td bgcolor='#FBB917'>$freePercent</td>"
# #FBB917
Add-Content $fileName "</tr>"
}
}
writeHtmlHeader $freeSpaceFileName
foreach ($server in Get-Content $script:list)
{
if(Test-Connection -ComputerName $server -Count 1 -ea 0) {
Add-Content $freeSpaceFileName "<table width='100%'><tbody>"
Add-Content $freeSpaceFileName "<tr bgcolor='#CCCCCC'>"
Add-Content $freeSpaceFileName "<td width='100%' align='center' colSpan=6><font face='tahoma' color='#003399' size='2'><strong> $server </strong></font></td>"
Add-Content $freeSpaceFileName "</tr>"
writeTableHeader $freeSpaceFileName
$dp = Get-WmiObject win32_logicaldisk -ComputerName $server | Where-Object {$_.drivetype -eq 3 }
foreach ($item in $dp)
{
Write-Host $item.DeviceID $item.VolumeName $item.FreeSpace $item.Size
writeDiskInfo $freeSpaceFileName $item.DeviceID $item.VolumeName $item.FreeSpace $item.Size
}
}
Add-Content $freeSpaceFileName "</table>"
}
writeHtmlFooter $freeSpaceFileName
Function sendEmail
{
param($from,$to,$subject,$smtphost,$htmlFileName)
[string]$receipients="$to"
$body = Get-Content $htmlFileName
$body = New-Object System.Net.Mail.MailMessage $from, $receipients, $subject, $body
$body.isBodyhtml = $true
$smtpServer = $MailServer
$smtp = new-object Net.Mail.SmtpClient($smtphost)
$smtp.Send($body)
}
# Email our report out
function Validate-IsEmail ([string]$Email)
{
return $Email -match "^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$"
}
$date = ( get-date ).ToString('yyyy/MM/dd')
sendEmail -from $EmailFrom -to $Emailto -subject "Disk Space Report - $Date" -smtphost $SMTPMail -htmlfilename $freeSpaceFileName
}