As an MCITP I’m well-versed in Group Policy and what not, but building a clean Windows base image with all updates applied and some prerequisite software has always always been a relatively manual, inconsistent, and annoying process. I recently did a major overhaul of our Operations Network/Server Infrastructure and figured there’s no better time to give my trusty Chef, Packer & Vagrant tool set a shot with our workstations.
Currently, I’ve got my OS X & *nix infrastructure under the control of Chef, and I’ve got e2e OS build & deployment processes in place (Packer -> Vagrant -> Chef ). As a well-versed, cross-platform expert, I figured it was about time to bring some of that over to the Windows side of our operation. Leveraging a DevOps skill set can cut back on the need for IT support personnel by automating trivial IT processes. In my opinion, anything that can be automated, should be automated… It is more efficient no matter which way you look at it.
I noticed that Windows 7 SP1 in particular seems to consume a TON of resources when looking for updates; this issue can literally cost you hours… It seems Microsoft has addressed this with KB3102810.
Here is a PowerShell function which you can throw in your provisioning script to tackle this issue.
Function Fix-WinUpdate {
# Retrieve Operating System Information
$OSInfo=(Get-WmiObject -Class Win32_OperatingSystem)
# FixUp Windows 7 SP1 & Server 2008 R2
If (($OSInfo).Version -eq '6.1.7601') {
If ([System.IntPtr]::Size -eq 4) { $osarch='x86' } else { $osarch='x64' }
If (($OSInfo).ProductType -eq 1) {
Write-Host 'Windows 7 SP1 Detected' -ForegroundColor 'Green'
$WUHotFixUrl = "https://download.microsoft.com/download/F/A/A/FAABD5C2-4600-45F8-96F1-B25B137E3C87/Windows6.1-KB3102810-${osarch}.msu"
}
Else
{
Write-Host 'Windows Server 2008 R2 Detected' -ForegroundColor 'Green'
$WUHotFixURL = 'https://download.microsoft.com/download/1/E/1/1E1E4FBD-9E64-4AF5-9494-592605CAE5D6/Windows6.1-KB3102810-x64.msu'
}
$WUHotFix = "C:\Windows\Temp\$($WUHotFixURL.Substring($WUHotFixURL.LastIndexOf('/') + 1))"
# Download & Install Latest Windows Update Client
If (!(Get-HotFix -Id 'KB3102810' -ErrorAction SilentlyContinue)) {
Write-Host "Downloading $(${OSInfo}.Caption) WU Client Update (KB3102810)"
(new-object net.webclient).DownloadFile($WUHotFixUrl, $WUHotFix)
Write-Host "Installing $(${OSInfo}.Caption) WU Client Update (KB3102810)"
Start-Process wusa -ArgumentList "${WUHotFix}", '/quiet' -Wait
Write-Host 'This update requires a reboot'
Restart-Host
}
}
# Windows Management Instrumentation Framework
$WMIUpdateUrl = "https://download.microsoft.com/download/3/D/6/3D61D262-8549-4769-A660-230B67E15B25/Windows6.1-KB2819745-${osarch}-MultiPkg.msu"
$WMIUpdate = "C:\Windows\Temp\$($WMIUpdateUrl.Substring($WMIUpdateUrl.LastIndexOf('/') + 1))"
# Download & Install Windows Management Instrumentation Framework 4.0
If (Test-Path 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client')
{
If (!(Get-HotFix -Id 'KB2819745' -ErrorAction SilentlyContinue)) {
Write-Host "Downloading $(${OSInfo}.Caption) WMI 4.0 (KB2819745)"
(new-object net.webclient).DownloadFile($WMIUpdateUrl, $WMIUpdate)
Write-Host "Installing $(${OSInfo}.Caption) WMI 4.0 (KB2819745)"
Start-Process wusa -ArgumentList "${WMIUpdate}", '/quiet' -Wait
Write-Host 'This update requires a reboot'
Restart-Host
}
}
}
}