|Create the Ultimate Smart PowerShell Update Script with Email Notifications and Error Handling
I wanted to create a smart PowerShell Script for updating our servers that was both ready to be executed manually as well as ready to be added as an automated task. Additionally, I wanted notifications to be generated whenever the script was run with details about the results, just in case we needed to debug any issues in the future. This is what I came up with:
# Basic Variables
$HostName = $env:COMPUTERNAME
$HostTime = get-date -Format hh:mm
$HostDate = get-date -format D
# SMTP Variables
$SMTPSender = "sender@member.buzz"
$SMTPRecipient = "recipient@member.buzz"
$SMTPMessage = New-Object System.Net.Mail.mailmessage $SMTPSender, $SMTPRecipient$SMTPMessage.IsBodyHTML = $true
$SMTPMessage.IsBodyHTML = $true
$SMTPMessage.Subject = $HostName + " Update Report"
$SMTPClient = new-Object Net.Mail.SmtpClient("smtpserver.com", 587)
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("SMTPUser", "SMTPPassword" )
# CHECK PENDING RESTART
# If the server already has a pending restart it should be done# before installing additional updates.if ((New-Object -ComObject Microsoft.Update.SystemInfo).RebootRequired){
$SMTPMessage.Body = "$($HostDate)
$($HostTime)
$($HostName) has a pending restart that must be completed before installing new updats."
$SMTPClient.Send($SMTPMessage) Restart-Computer -Force}else{ # SEARCH UPDATES # This will find new updates to install. $UpdateResults = (New-Object -ComObject Microsoft.Update.Searcher).Search("IsInstalled=0 and Type='Software'").Updates # CHECK UPDATE COUNT # If there are no updates and you attempt to call # download, an exception is thrown.
if ($UpdateResults.Count -eq 0)
{
$SMTPMessage.Body = "$($HostDate)
$($HostTime)
$($HostName) has checked for updates but coult not find any." $SMTPClient.Send($SMTPMessage)
}
else
{
# DOWNLOAD UPDATES
# Attempt to download updates, writing progress as it goes.
$UpdateDownloader = (New-Object -ComObject Microsoft.Update.Session).CreateUpdateDownloader()
$UpdateDownloader.Updates = $UpdateResults
write-progress -Activity 'Updating' -Status "Downloading $($UpdateDownloader.Updates.count) updates"
$UpdateDownloader.Download()
# INSTALL UPDATES
# Installs the updates that have been downloaded.
$UpdateInstaller = New-Object -ComObject Microsoft.Update.Installer
$UpdateInstaller.Updates = $UpdateResults
$UpdateResult = $UpdateInstaller.Install()
if ($UpdateResult.rebootRequired)
{
$SMTPMessage.Body = "$($HostDate)
$($HostTime)
$($HostName) has installed all available updates and will now reboot."
$SMTPClient.Send($SMTPMessage)
Restart-Computer -Force
}
else
{
$SMTPMessage.Body = "$($HostDate)
$($HostTime)
$($HostName) has installed all available updates and no reboot is required."
$SMTPClient.Send($SMTPMessage) } }}
If you are okay with less control over how your updates work (and don't need notifications), you can use a pre-existing library using the following script:
Set-ExecutionPolicy RemoteSigned -ForceInstall-PackageProvider -Name NuGet -ForceSet-PSRepository -Name "PSGallery" -InstallationPolicy TrustedInstall-Module PSWindowsUpdateImport-Module PSWindowsUpdateAdd-WUServiceManager -ServiceID 7971f918-a847-4430-9279-4a52d1efe18d -Confirm:$falseGet-WUInstall -AcceptAll -Install -AutoReboot
Finally, if this is an automated task, set your Action to start a program (PowerShell.exe) with the following arguments:
sds
Happy scripting!
Other resources: