13 January 2014

Apply Updates and Hotfixes online

This script is intended to apply updates and hotfixes after the OS has been installed and is online. There are windows updates that cannot be installed offline, as described in this blog. For these updates, I have written a script that will apply the updates using wusa.exe. In order to properly install them, I recommend numbering the filenames so that the script will read them in the correct sequence. I added 01-, 02-, 03-, etc in front of the filename. The script now reads the files in that sequence. The script has been written so that it only reads msu files. You can download this script here.

 #   Author: Mick Pletcher  
 #    Date: 01 January 2014  
 #   Program: Online Windows Updates Installer  
 #Declare Local Memory  
 Set-Variable -Name File -Scope Local -Force  
 Function DeclareGlobalMemory {  
      Set-Variable -Name Files -Scope Global -Force  
      Set-Variable -Name RelativePath -Scope Global -Force  
 Function GlobalMemoryCleanup {  
      Remove-Variable -Name Files -Scope Global -Force  
      Remove-Variable -Name RelativePath -Scope Global -Force  
 Function RenameWindow ($Title) {  
      #Declare Local Memory  
      Set-Variable -Name a -Scope Local -Force  
      $a = (Get-Host).UI.RawUI  
      $a.WindowTitle = $Title  
      #Cleanup Local Memory  
      Remove-Variable -Name a -Scope Local -Force  
 Function GetRelativePath {  
      $Global:RelativePath=(split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"  
 Function GetFiles {  
      $Global:Files = Get-ChildItem -Path $Global:RelativePath  
 Function CreateTempFolder ($FolderName) {  
      $FolderName = "c:\temp\"+$FolderName  
      New-Item -Path $FolderName -ItemType Directory -Force  
 Function RemoveTempFolder ($FolderName) {  
      $FolderName = "c:\temp\"+$FolderName  
      Remove-Item -Path $FolderName -Recurse -Force  
 Function ExtractCAB ($Name) {  
      #Declare Local Memory  
      Set-Variable -Name arguments -Scope Local -Force  
      Set-Variable -Name Dest -Scope Local -Force  
      Set-Variable -Name Source -Scope Local -Force  
      $Source = $Global:RelativePath+$Name  
      $Dest = "c:\temp\"+$Name.Substring(0,$Name.Length-4)  
      $arguments = "–F:*"+[char]32+$Source+[char]32+$Dest  
      Start-Process -FilePath "expand.exe" -ArgumentList $arguments -Wait -PassThru  
      #Cleanup Local Memory  
      Remove-Variable -Name arguments -Scope Local -Force  
      Remove-Variable -Name Dest -Scope Local -Force  
      Remove-Variable -Name Source -Scope Local -Force  
 #Function ApplyWindowsUpdate ($Name,$Directory) {  
 #     #Declare Local Memory  
 #     Set-Variable -Name arguments -Scope Local -Force  
 #     $Name = $Name.Substring(0,$Name.Length-4)  
 #     $Name = $Name+".cab"  
 #     $arguments = "/Online /Add-Package /PackagePath:"+"c:\temp\"+$Directory+"\"+$Name  
 #     Start-Process -FilePath "DISM.exe" -ArgumentList $arguments -Wait -PassThru  
 #     #Cleanup Local Memory  
 #     Remove-Variable -Name arguments -Scope Local -Force  
 Function ApplyWindowsUpdate ($Name) {  
      #Declare Local Memory  
      Set-Variable -Name App -Scope Local -Force  
      Set-Variable -Name arguments -Scope Local -Force  
      Set-Variable -Name index -Scope Local -Force  
      Set-Variable -Name Result -Scope Local -Force  
      $App = $Name  
      $index = $App.IndexOf("-KB")+1  
      $App = $App.Substring(0,$App.Length-4)  
      $App = $App.Substring($index)  
      Write-Host "Installing"$App"....." -NoNewline  
      $arguments = $Global:RelativePath+$Name+[char]32+"/quiet /norestart"  
      $Result = (Start-Process -FilePath "wusa.exe" -ArgumentList $arguments -Wait -PassThru).ExitCode  
      If ($Result -eq "3010") {  
           Write-Host "Succeeded" -ForegroundColor Yellow  
      } else {  
           Write-Host "Failed with error code"$Result -ForegroundColor Red  
      #Cleanup Local Memory  
      Remove-Variable -Name App -Scope Local -Force  
      Remove-Variable -Name arguments -Scope Local -Force  
      Remove-Variable -Name index -Scope Local -Force  
      Remove-Variable -Name Result -Scope Local -Force  
 RenameWindow "Windows Updates"  
 foreach ($File in $Files) {  
      if (($File.Attributes -ne "Directory") -and ($File.Name -like "*.msu")) {  
           ApplyWindowsUpdate $File.Name  
 #Cleanup Local Memory  
 Remove-Variable -Name File -Scope Local -Force  


  1. That is very helpful, I am thinking to put that into our servers!
    Save our time to install the updates into the servers, one by one!