Deploying KB3025945 Using the ConfigMgr Package Model

We recently had some reports of IE9 crashing after installing a MS patch KB3008923 released December 9th, 2014.  A few days ago on January 22nd, 2015 MS released an update that fixes the issue, KB3025945.  Unfortunately at the time of writing, the update is not available on WSUS, so it must be manually downloaded and deployed.  I decided to deploy the patch using ConfigMgr to the affected machines.  Of course, you could use SCUP to deploy the patch using the Software Updates model, but I decided to use the standard Package and Program model instead, with some Powerhelp ;).  Here’s a step-by-step guide for deploying the patch.  I’m using ConfigMgr 2012 R2 CU3.

Create a Collection

First, we need to identify all the machines that may be affected by this issue.  According to the KB, it only affects machines that have the KB3008923 installed, Internet Explorer 9, and the following operating systems: Windows 7 SP1, Windows 2008 SP2 and Windows 2008 R2.

Let’s use a little Powershell to create the collection and add the query rule that will filter for affected machines.  I’m using a limiting collection called ‘All SCCM 2012 Clients’, and I’m using Software Inventory to determine the IE version installed and the Win32_QuickFixEngineering WMI class to determine installed patches, so make sure that’s all enabled in your client settings (Software Inventory, Hardware Inventory classes).


# Create the collection
New-CMDeviceCollection -LimitingCollectionName "All SCCM 2012 Clients" -Name "KB3025945" `
-Comment "Manual deployment of patch KB3025945 to all Win 7 SP1, W2K8 R2 SP1 and W2K8 SP2 machines with KB3008923 and IE9 installed" `
-RefreshType Periodic

# Add the query rule
Add-CMDeviceCollectionQueryMembershipRule -CollectionName "KB3025945" -QueryExpression `
"select SMS_R_System.Name, SMS_G_System_OPERATING_SYSTEM.Caption, SMS_G_System_OPERATING_SYSTEM.Version
from SMS_R_System
inner join SMS_G_System_QUICK_FIX_ENGINEERING on SMS_G_System_QUICK_FIX_ENGINEERING.ResourceID = SMS_R_System.ResourceId
inner join SMS_G_System_SoftwareFile on SMS_G_System_SoftwareFile.ResourceID = SMS_R_System.ResourceId
inner join SMS_G_System_OPERATING_SYSTEM on SMS_G_System_OPERATING_SYSTEM.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_SoftwareFile.FilePath like ""%\\Program Files\\Internet Explorer\\""
and SMS_G_System_SoftwareFile.FileName like ""iexplore.exe""
and SMS_G_System_SoftwareFile.FileVersion like ""9.%"" and
SMS_G_System_QUICK_FIX_ENGINEERING.HotFixID = ""KB3008923"" and
SMS_G_System_OPERATING_SYSTEM.Caption in (
""Microsoft Windows 7 Enterprise"",
""Microsoft Windows 7 Enterprise K"",
""Microsoft Windows 7 Enterprise N"",
""Microsoft Windows 7 Professional"",
""Microsoft Windows 7 Ultimate"",
""Microsoft Windows Server 2008 R2 Enterprise"",
""Microsoft Windows Server 2008 R2 Standard"",
""Microsoft® Windows Server® 2008 Enterprise"",
""Microsoft® Windows Server® 2008 Standard""
)
and SMS_G_System_OPERATING_SYSTEM.Version in (""6.0.6002"",""6.1.7601"")" `
-RuleName "KB3008923 / IE9"

Download the Patches

Great, now we have the collection, let’s download the patches from the Microsoft Update Catalog and save them to our SCCM package source.  There are 5 patches available for the different OS’s, so I’m gonna download them all.

Capture

Create the Packages, Programs and Deployments with Powershell

Lets make life easy again and use the native ConfigMgr Powershell cmdlets to do the work for us.

First off, I’m setting the Package and Program property variables as these will be common to all the packages.  Be sure to add your distribution point group name.  Further down in the script, from line 36, we need to set the package source location ($source) for each of the packages we will create for the different OS’s.  If you are happy with the Package name ($Pkg) you can leave it as is, and the command-lines are populated for you.  Since the installers are msu files, we will use WUSA.exe to install them silently with the /quiet and /norestart switches.  We will deploy the packages to the collection we created, simply named ‘KB3025945’.

I’m choosing to create a Required deployment that will begin as soon as possible, and I’m suppressing any notifications as I prefer to deploy silently in most cases, but you can of course change these settings in the script.

Run the script, and it will create the packages, programs, deployments, and distribute the package content.


<#
----------------
Deploy KB3025945
----------------

This script creates packages and programs for KB3025945, distributes the packages and deploys them.

Set the variables below as required
#>
## Set Package / Program Properties

# Required amount of disk space
$DiskSpace = "100"
# Units for Disk space requirement, eg KB, MB or GB
$DiskUnit = "MB"
# Maximum allowed run time
$Duration = "16"
# Program can run, eg "WhetherOrNotUserIsLoggedOn", "OnlyWhenNoUserIsLoggedOn", "OnlyWhenUserIsLoggedOn"
$RunType = "WhetherOrNotUserIsLoggedOn"
# Run mode, eg "RunWithAdministrativeRights" or "RunWithUserRights"
$RunMode = "RunWithAdministrativeRights"
# Allow user to interact?
$UserInteraction = $False
# Allow program to be installed from task sequence?
$EnableTS = $True
# Distribution Point Group Name
$DPG = "All Distribution Points"
# Set OS versions as array
$OSes = "Win7","Win7x64","W2K8","W2K8R2","W2K8x64"
## Set error action
$ErrorActionPreference = "Stop"
foreach ($OS in $OSes)
{

# Set Package source location and file names
if ($OS -eq "Win7")
{
$Pkg = "KB3025945 - Windows 7 SP1 x86"
$Source = "\\sccmserver-01\SoftwareUpdates\Out-of-Band Patches\KB3025945\Update for Windows 7 (KB3025945)"
$CommandLine = "wusa.exe X86-all-ie9-windows6.1-kb3025945-x86_ba77aa242aa4a0991c8879f9a04aaedd4c4b67c0.msu /quiet /norestart"
}
if ($OS -eq "Win7x64")
{
$Pkg = "KB3025945 - Windows 7 SP1 x64"
$Source = "\\sccmserver-01\SoftwareUpdates\Out-of-Band Patches\KB3025945\Update for Windows 7 for x64-based Systems (KB3025945)"
$CommandLine = "wusa.exe AMD64-all-ie9-windows6.1-kb3025945-x64_6566d74c6f14e6d4b120d2b07d91711f2e4c7dc9.msu /quiet /norestart"
}
if ($OS -eq "W2K8")
{
$Pkg = "KB3025945 - Windows Server 2008 x86 SP2"
$Source = "\\sccmserver-01\SoftwareUpdates\Out-of-Band Patches\KB3025945\Update for Windows Server 2008 (KB3025945)"
$CommandLine = "wusa.exe X86-all-ie9-windows6.0-kb3025945-x86_4a6f65fe4b418deb3e9626ba86234c3db718f85f.msu /quiet /norestart"
}
if ($OS -eq "W2K8R2")
{
$Pkg = "KB3025945 - Windows Server 2008 R2 SP1"
$Source = "\\sccmserver-01\SoftwareUpdates\Out-of-Band Patches\KB3025945\Update for Windows Server 2008 R2 x64 Edition (KB3025945)"
$CommandLine = "wusa.exe AMD64-all-ie9-windows6.1-kb3025945-x64_6566d74c6f14e6d4b120d2b07d91711f2e4c7dc9.msu /quiet /norestart"
}
if ($OS -eq "W2K8x64")
{
$Pkg = "KB3025945 - Windows Server 2008 x64 SP2"
$Source = "\\sccmserver-01\SoftwareUpdates\Out-of-Band Patches\KB3025945\Update for Windows Server 2008 x64 Edition (KB3025945)"
$CommandLine = "wusa.exe AMD64-all-ie9-windows6.0-kb3025945-x64_5cb8756529a63243805301e4e26f375bb6819fc1.msu /quiet /norestart"
}

## Create the Package ##

write-host "Creating Package: $Pkg" -foregroundcolor Green
try
{
$Package = New-CMPackage -Name $Pkg -Path $Source
}
catch { write-host "Could not create new package.`n$($_.Exception.Message)" -ForegroundColor Red; break }

## Create a Program

write-host 'Adding Program'
try
{
$Program = New-CMProgram `
-PackageName $Pkg `
-StandardProgramName $Pkg `
-CommandLine $CommandLine `
-DiskSpaceRequirement $DiskSpace `
-DiskSpaceUnit $DiskUnit `
-Duration $Duration `
-ProgramRunType $RunType `
-RunMode $RunMode `
-UserInteraction $UserInteraction
}
catch { write-host "Could not add program.`n$($_.Exception.Message)" -ForegroundColor Red; break }

## Update Program

write-host 'Updating Program'
try
{
$ProgramUpdate = Set-CMProgram `
-Name $Pkg `
-ProgramName $Pkg `
-StandardProgram `
-EnableTaskSequence $EnableTS
}
catch { write-host "Could not update program.`n$($_.Exception.Message)" -ForegroundColor Red; break }

## Distribute Content to DPs ##

write-host 'Distributing Content to DPs'
try
{
Start-CMContentDistribution -PackageName $Pkg -DistributionPointGroupName $DPG
}
catch { write-host "Could not distribute package.`n$($_.Exception.Message)" -ForegroundColor Red; break }


## Deploy the package

write-host "Deploying the package...please wait"
try
{
Start-CMPackageDeployment -CollectionName "KB3025945" `
-PackageName $pkg `
-ProgramName $pkg `
-StandardProgram `
-DeployPurpose Required `
-FastNetworkOption DownloadContentFromDistributionPointAndRunLocally `
-SlowNetworkOption DownloadContentFromDistributionPointAndLocally `
-SoftwareInstallation $true `
-SystemRestart $false `
-ScheduleEvent AsSoonAsPossible `
-RerunBehavior RerunIfFailedPreviousAttempt
}
catch { write-host "Could not deploy the package.`n$($_.Exception.Message)" -ForegroundColor Red; break }


}
write-host 'Done!' -ForegroundColor Yellow

Set the OS Requirement on the Programs

Great, now I have everything done…well, nearly everything…

Capture2

Capture4

Capture5

A limitation of the native Powershell cmdlets is that we can’t set the OS requirement on the Programs, so we need to do that in the console.  In the Properties of each program, set the relevant OS:

Capture3

That’s it!  Installation logging will appear in the WindowsUpdate.log on the client.  Since we did not enforce a reboot the clients will install the patch, but it will remain in the ‘reboot pending’ state until a reboot has been performed.  You can monitor your deployment using the standard methods in the ConfigMgr console or the built-in reports.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s