#===========================================================================================================================
Script Name: GetServerUpdates.ps1
Description: Reports on the last date a patch was installed on servers.
Inputs: List of server names fed from text file, one server name per line.
Outputs: Report showing Server name, date and time patched, and how many days ago the server was patched.
Notes:
Example: .\GetServerUpdates.ps1
Author: Richard Wright
Date Created: 11/3/2017
Credits:
Last Revised: 7:44 AM 12/20/2017
ChangeLog: Date Who Description of changes
11/04/2017 RMW Added BG colors to highlight good, warning, critical days.
11/06/2017 RMW Added email notification.
12/06/2017 RMW Changed the querying processes
12/20/2017 RWM Aestetics, shared on Spiceworks
=============================================================================================================================
Edit these with your preferences in the section following this one:
$DateStamp = the format of dates shown in the report.
$FileDateStamp = Appends yyyyMMdd to the Report File.
$ServerList = File with the list of servernames for which to provide patch statistics; one per line.
$ReportFileName = The outputted HTML filename and location
$ReportTitle = Name of the report that is shown in the generated HTML file and in email subject.
$EmailTo = Who should receive the report via email
$EmailCc = Who should receive the report via email Cc:
$EmailFrom = Sender email address
$EmailSubject = Subject for the email
$SMTPServer = SMTP server name
$BGColorTbl = Background color for tables.
$BGColorGood = Background color for "Good" results. #4CBB17 is green.
$BGColorWarn = Background color for "Warning" results. #FFFC33 is yellow.
$BGColorCrit = Background color for "Critical" results. #FF0000 is red.
$Warning = # of days since last update to indicate Warning (Yellow) in report. Must be less than $Critical amount.
$Critical = # of days since last update to indicate Critical (RED) in report. Must be more than $Warning amount.
=============================================================================================================================#>
$DateStamp = (Get-Date -Format D)
$FileDateStamp = Get-Date -Format yyyyMMdd
$ServerList = Get-Content "C:\Admin\ServerList.txt"
$ScriptPath = Get-Location
$ReportFileName = "$ScriptPath\ServerPatchReport-$FileDateStamp.html"
$ReportTitle = "Server Patch Report"
$EmailTo = "emailto@domain.com"
#$EmailCc = "EmailCc@domain.com"
$EmailFrom = "noreply@domain.com"
$EmailSubject = "Server Patch Report for $DateStamp"
$SMTPServer = "SMTPServerName"
$BGColorTbl = "#EAECEE"
$BGColorGood = "#4CBB17"
$BGColorWarn = "#FFFC33"
$BGColorCrit = "#FF0000"
$Warning = 30
$Critical = 90
<#==================================================
Do not edit below this section
==================================================#>
Clear
<#==================================================
Begin MAIN
==================================================#>
# Create output file and nullify display output
New-Item -ItemType file $ReportFileName -Force > $null
<#==================================================
Write the HTML Header to the report file
==================================================#>
Add-Content $ReportFileName ""
Add-Content $ReportFileName "
"
Add-Content $ReportFileName ""
Add-Content $ReportFileName "$ReportTitle"
Add-Content $ReportFileName '"
Add-Content $ReportFileName ""
Add-Content $ReportFileName ""
Add-Content $ReportFileName ""
Add-Content $ReportFileName ""
Add-Content $ReportFileName ""
Add-Content $ReportFileName "$ReportTitle "
Add-Content $ReportFileName "$DateStamp
"
# Add color descriptions
Add-content $ReportFileName ""
Add-Content $ReportFileName ""
Add-Content $ReportFileName "Patched < $Warning Days | "
Add-Content $ReportFileName "Patched $Warning - $Critical Days | "
Add-Content $ReportFileName "Patched > $Critical Days | "
Add-Content $ReportFileName " "
Add-Content $ReportFileName " "
# Add Column Headers
Add-Content $ReportFileName " | "
Add-Content $ReportFileName "
"
Add-Content $ReportFileName ""
Add-Content $ReportFileName "Server Name | "
Add-Content $ReportFileName "Last Patch Date & Time | "
Add-Content $ReportFileName "Days Since Last Patch | "
Add-Content $ReportFileName "
"
<#==================================================
Function to write the HTML footer
==================================================#>
Function writeHtmlFooter
{
param($FileName)
Add-Content $FileName "
"
Add-content $FileName ""
Add-Content $FileName ""
Add-Content $FileName "Total Servers: $ServerCount | "
Add-Content $FileName "
"
Add-Content $FileName "
"
Add-Content $FileName ""
Add-Content $FileName ""
}
<#==================================================
Function to write server update information to the
HTML report file
==================================================#>
Function writeUpdateData
{
param($FileName,$Server,$InstalledOn)
Add-Content $FileName ""
Add-Content $FileName "$Server | "
Add-Content $FileName "$InstalledOn | "
# Color BG depending on $Warning and $Critical days set in script
If ($InstalledOn -eq "Error collecting data")
{
$DaySpanDays = "Error"
}
Else
{
$System = (Get-Date -Format "MM/dd/yyyy hh:mm:ss")
$DaySpan = New-TimeSpan -Start $InstalledOn -End $System
$DaySpanDays = $DaySpan.Days
}
If ($InstalledOn -eq "Error collecting data" -or $DaySpan.Days -gt $Critical)
{
# Red for Critical or Error retrieving data
Add-Content $FileName "$DaySpanDays | "
Add-Content $FileName "
"
}
ElseIf ($DaySpan.Days -le $Warning)
{
# Green for Good
Add-Content $FileName "$DaySpanDays | "
Add-Content $FileName ""
}
Else
{
# Yellow for Warning
Add-Content $FileName "$DaySpanDays | "
Add-Content $FileName ""
}
Add-Content $FileName ""
}
<#==================================================
Query servers for their update history
Try registry first, if error Get-Hotfix
==================================================#>
Write-Host "Querying servers for installed updates..." -foreground "Yellow"
$ServerCount = 0
ForEach ($Server in $ServerList)
{
Try
{
Write-host "Checking $Server..."
$ServerCount++
$key = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install"
$keytype = [Microsoft.Win32.RegistryHive]::LocalMachine
$RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$Server)
$regKey = $RemoteBase.OpenSubKey($key)
$KeyValue = ""
$KeyValue = $regkey.GetValue("LastSuccessTime")
$InstalledOn = ""
$InstalledOn = Get-Date $KeyValue -Format 'MM/dd/yyyy hh:mm:ss'
}
Catch
{
$ServerLastUpdate = (Get-HotFix -ComputerName $Server | Sort-Object -Descending -Property InstalledOn -ErrorAction SilentlyContinue | Select-Object -First 1)
$InstalledOn = $ServerLastUpdate.InstalledOn
}
If ($InstalledOn -eq "")
{
$InstalledOn = "Error collecting data"
}
writeUpdateData $ReportFileName $Server $InstalledOn
}
Write-Host "Finishing report..." -ForegroundColor "Yellow"
writeHtmlFooter $ReportFileName
<#==================================================
Send email
==================================================#>
Write-Host "Sending email..."
$BodyReport = Get-Content "$ReportFileName" -Raw
$StopEmailLoop=$false
[int]$RetryCount=0
Do
{
Try
{
Send-MailMessage -To $EmailTo `
-Subject $EmailSubject `
-From $EmailFrom `
-SmtpServer $SMTPServer `
-BodyAsHtml -Body $BodyReport `
-ErrorAction Stop;
$StopEmailLoop = $true
}
Catch
{
If ($RetryCount -gt 5)
{
Write-Host "Cannot send email. The script will exit."
$StopEmailLoop = $true
}
Else
{
Write-Host "Cannot send email. Will try again in 15 seconds..."
Start-Sleep -Seconds 15
$RetryCount = $RetryCount+1
}
}
}
While ($StopEmailLoop -eq $false)