18 January 2016

Installing Microsoft Updates in the Build Post-OS

There are updates that have to be installed after the OS has been installed. .Net Framework is an example. When I am building a reference image, I cannot inject the updates as packages to .Net Framework as it is not installed until after the OS has been installed. There have also been cases where an MSU could not be injected before the OS was installed. It would kill the build. I don't want to waste time having to wait on the windows update task to download, verify, and install the update.  This script will solve these issues. The script is designed to get all EXE and MSU files in the same directory as the InstallOnlineUpdates.ps1 PowerShell script and install them.

The first thing you want to do is let the reference image complete. Once it is finished, look at the ZTIWindowsUpdate.log file. It will show all updates that were downloaded and installed during the Windows Update task. The next thing is to download the updates, which can easily be done at https://catalog.update.microsoft.com/. Once you have the updates downloaded, place them in the same directory as this PowerShell script. In order to sequence these out, number them starting from 01 and etc. You can see how I have done mine in the screenshot below. I put EXE and MSU in the front of the filename so they would be separated and easy to find. 

Now all you have to do is to create an application to execute the PowerShell script and it will install all of your EXE and MSU files that need to be installed post-OS. 

You can download the script from here.

1:  <#       
2:       .NOTES  
3:       ===========================================================================  
4:        Created with:     SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99  
5:        Created on:       1/18/2016 1:41 PM  
6:        Created by:       Mick Pletcher  
7:        Organization:         
8:        Filename:        InstallOnlineUpdates.ps1  
9:       ===========================================================================  
10:       .DESCRIPTION  
11:            This script will install both exe updates and msu updates. It is  
12:            intended to be used during the generation of a reference image. Not  
13:            all updates can be injected offline into the OS. This script takes  
14:            care of those by running post-OS install.  
15:  #>  
18:  function Install-EXEUpdates {  
19:       #Declare Variables  
20:       Set-Variable -Name Arguments -Scope Local -Force  
21:       Set-Variable -Name ErrCode -Scope Local -Force  
22:       Set-Variable -Name File -Scope Local -Force  
23:       Set-Variable -Name EXEFiles -Scope Local -Force  
24:       Set-Variable -Name RelativePath -Scope Local -Force  
26:       $RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
27:       $EXEFiles = Get-ChildItem -Path $RelativePath -Force | where { $_.Name -like "*.exe*" }  
28:       If ($EXEFiles.Count -ge 1) {  
29:            $EXEFiles | Sort-Object  
30:            cls  
31:            foreach ($File in $EXEFiles) {  
32:                 $Arguments = "/passive /norestart"  
33:                 Write-Host "Installing"$File.Name"....." -NoNewline  
34:                 $ErrCode = (Start-Process -FilePath $File.Fullname -ArgumentList $Arguments -Wait -Passthru).ExitCode  
35:                 If ($ErrCode -eq 0) {  
36:                      Write-Host "Success" -ForegroundColor Yellow  
37:                 } else {  
38:                      Write-Host "Failed with error code"$ErrCode -ForegroundColor Red  
39:                 }  
40:            }  
41:       }  
43:       #Cleanup Local Variables  
44:       Remove-Variable -Name Arguments -Scope Local -Force  
45:       Remove-Variable -Name ErrCode -Scope Local -Force  
46:       Remove-Variable -Name File -Scope Local -Force  
47:       Remove-Variable -Name EXEFiles -Scope Local -Force  
48:       Remove-Variable -Name RelativePath -Scope Local -Force  
49:  }  
51:  function Install-MSUUpdates {  
52:       #Declare Variables  
53:       Set-Variable -Name Arguments -Scope Local -Force  
54:       Set-Variable -Name ErrCode -Scope Local -Force  
55:       Set-Variable -Name Executable -Value $env:windir"\System32\wusa.exe" -Scope Local -Force  
56:       Set-Variable -Name File -Scope Local -Force  
57:       Set-Variable -Name MSUFiles -Scope Local -Force  
58:       Set-Variable -Name RelativePath -Scope Local -Force  
60:       $RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"  
61:       $MSUFiles = Get-ChildItem -Path $RelativePath -Force | where { $_.Name -like "*.msu*" }  
62:       If ($MSUFiles.Count -ge 1) {  
63:            $MSUFiles | Sort-Object  
64:            cls  
65:            foreach ($File in $MSUFiles) {  
66:                 $Arguments = $File.FullName + [char]32 + "/quiet /norestart"  
67:                 Write-Host "Installing"$File.Name"....." -NoNewline  
68:                 $ErrCode = (Start-Process -FilePath $Executable -ArgumentList $Arguments -Wait -Passthru).ExitCode  
69:                 If (($ErrCode -eq 0) -or ($ErrCode -eq 2359302)) {  
70:                      Write-Host "Success" -ForegroundColor Yellow  
71:                 } else {  
72:                      Write-Host "Failed with error code"$ErrCode -ForegroundColor Red  
73:                 }  
74:            }  
75:       }  
77:       #Cleanup Local Variables  
78:       Remove-Variable -Name Arguments -Scope Local -Force  
79:       Remove-Variable -Name ErrCode -Scope Local -Force  
80:       Remove-Variable -Name Executable -Scope Local -Force  
81:       Remove-Variable -Name File -Scope Local -Force  
82:       Remove-Variable -Name MSUFiles -Scope Local -Force  
83:       Remove-Variable -Name RelativePath -Scope Local -Force  
84:  }  
86:  cls  
87:  Install-EXEUpdates  
88:  Install-MSUUpdates  
89:  Start-Sleep -Seconds 5  


Post a Comment