PoshCode Logo PowerShell Code Repository

Invoke-WindowsUpdate by Jan Egil Ring 6 years ago
View followups from Daniel and brianclark44 | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1932"></script>download | new post

Script to download and install updates from Windows Update/WSUS. Reporting and rebooting may be customized.
For more details, see the following blog-post:
http://blog.powershell.no/2010/06/25/manage-windows-update-installations-using-windows-powershell

  1. ###########################################################################"
  2. #
  3. # NAME: Invoke-WindowsUpdate.ps1
  4. #
  5. # AUTHOR: Jan Egil Ring
  6. # EMAIL: jan.egil.ring@powershell.no
  7. #
  8. # COMMENT: Script to download and install updates from Windows Update/WSUS. Reporting and rebooting may be customized.
  9. #          For more details, see the following blog-post:
  10. #          http://blog.powershell.no/2010/06/25/manage-windows-update-installations-using-windows-powershell
  11. #
  12. # You have a royalty-free right to use, modify, reproduce, and
  13. # distribute this script file in any way you find useful, provided that
  14. # you agree that the creator, owner above has no warranty, obligations,
  15. # or liability for such use.
  16. #
  17. # VERSION HISTORY:
  18. # 1.0 25.06.2010 - Initial release
  19. #
  20. ###########################################################################"
  21.  
  22. #Requires -Version 2.0
  23.  
  24. #Variables to customize
  25. $EmailReport = $true
  26. $FileReport = $true
  27. $To = "it-reports@domain.com"
  28. $From = "powershell@domain.com"
  29. $SMTPServer = "smtp.domain.local"
  30. $FileReportPath = "\\domain.local\IT\Windows Update Reports\"
  31. $AutoRestart = $true
  32. $AutoRestartIfPending = $true
  33.  
  34. $Path = $FileReportPath + "$env:ComputerName" + "_" + (Get-Date -Format dd-MM-yyyy_HH-mm).ToString() + ".html"
  35.  
  36. #Testing if there are any pending reboots from earlier Windows Update sessions
  37. if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"){
  38.  
  39. #Report to e-mail if enabled
  40. if ($EmailReport -eq $true) {
  41. $pendingboot = @{$false="was pending for a restart from an earlier Windows Update session. Due to the reboot preferences in the script, a reboot was not initiated."; $true="was restarted due to a pending restart from an earlier Windows Update session."}
  42. $status = $pendingboot[$AutoRestartIfPending]
  43.  $messageParameters = @{                        
  44.                 Subject = "Windows Update report for $env:ComputerName.$env:USERDNSDOMAIN - $((Get-Date).ToShortDateString())"                        
  45.                 Body = "Invoke-WindowsUpdate was run on $env:ComputerName, and the server $status `nPlease run Invoke-WindowsUpdate again when the server is rebooted."              
  46.                 from = $From                        
  47.                 To = $To                      
  48.                 SmtpServer = $SMTPServer                        
  49.             }                        
  50.             Send-MailMessage @messageParameters -BodyAsHtml
  51.  
  52. #Report to file if enabled
  53. if ($FileReport -eq $true) {
  54. "Invoke-WindowsUpdate was run on $env:ComputerName, and the server $status `nPlease run Invoke-WindowsUpdate again when the server is rebooted." | Out-File -FilePath $path
  55. }
  56.  
  57. #Reboot if autorestart for pending updates is enabled
  58. if ($AutoRestartIfPending) {shutdown.exe /t 0 /r }  }
  59. exit
  60.                        
  61. }
  62.  
  63. #Checking for available updates
  64. $updateSession = new-object -com "Microsoft.Update.Session"
  65. write-progress -Activity "Updating" -Status "Checking available updates"  
  66. $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates
  67. $downloader = $updateSession.CreateUpdateDownloader()          
  68. $downloader.Updates = $Updates
  69.  
  70. #If no updates available, do nothing
  71. if ($downloader.Updates.Count -eq "0") {
  72.  
  73. #Report to e-mail if enabled
  74. if ($EmailReport -eq $true) {
  75.  $messageParameters = @{                        
  76.                 Subject = "Windows Update report for $env:ComputerName.$env:USERDNSDOMAIN - $((Get-Date).ToShortDateString())"                        
  77.                 Body = "Invoke-WindowsUpdate was run on $env:ComputerName, but no new updates were found. Please try again later."              
  78.                 from = $From                        
  79.                 To = $To                      
  80.                 SmtpServer = $SMTPServer                        
  81.             }                        
  82.             Send-MailMessage @messageParameters -BodyAsHtml
  83.                         }
  84.                        
  85. #Report to file if enabled
  86. if ($FileReport -eq $true) {
  87. "Invoke-WindowsUpdate was run on $env:ComputerName, but no new updates were found. Please try again later." | Out-File -FilePath $Path
  88. }
  89.  
  90. }
  91. else
  92. {
  93. #If updates are available, download and install
  94. write-progress -Activity 'Updating' -Status "Downloading $($downloader.Updates.count) updates"  
  95.  
  96. $Criteria="IsInstalled=0 and Type='Software'"
  97. $resultcode= @{0="Not Started"; 1="In Progress"; 2="Succeeded"; 3="Succeeded With Errors"; 4="Failed" ; 5="Aborted" }
  98. $Result= $downloader.Download()
  99.  
  100. if (($Result.Hresult -eq 0)and (($result.resultCodeeq 2) -or ($result.resultCodeeq 3)) ) {
  101.        $updatesToInstall = New-object -com "Microsoft.Update.UpdateColl"
  102.        $Updates | where {$_.isdownloaded} | foreach-Object {$updatesToInstall.Add($_) | out-null
  103. }
  104.  
  105. $installer = $updateSession.CreateUpdateInstaller()      
  106. $installer.Updates = $updatesToInstall
  107.  
  108. write-progress -Activity 'Updating' -Status "Installing $($Installer.Updates.count) updates"        
  109.  
  110. $installationResult = $installer.Install()        
  111. $Global:counter=-1      
  112.  
  113. $Report = $installer.updates |
  114.                                 Select-Object -property Title,EulaAccepted,@{Name='Result';expression={$ResultCode[$installationResult.GetUpdateResult($Global:Counter++).resultCode ] }},@{Name='Reboot required';expression={$installationResult.GetUpdateResult($Global:Counter++).RebootRequired }} |
  115.                                 ConvertTo-Html
  116.  
  117. #Report to e-mail if enabled
  118. if ($EmailReport -eq $true) {
  119.  $messageParameters = @{                        
  120.                 Subject = "Windows Update report for $env:ComputerName.$env:USERDNSDOMAIN - $((Get-Date).ToShortDateString())"                        
  121.                 Body =  $Report | Out-String                
  122.                 from = $From                        
  123.                 To = $To                      
  124.                 SmtpServer = $SMTPServer                        
  125.             }                        
  126.             Send-MailMessage @messageParameters -BodyAsHtml
  127.                         }
  128.  
  129. #Report to file if enabled
  130. if ($FileReport -eq $true) {
  131. $Report | Out-File -FilePath $path
  132. }
  133.  
  134. #Reboot if autorestart is enabled and one or more updates are requiring a reboot
  135. if ($autoRestart -and $installationResult.rebootRequired) { shutdown.exe /t 0 /r }      
  136. }
  137. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me