Managing Software Updates on the ConfigMgr Server – Part 2

Dec 15th, 2011

Once you have an update list created (either manually or via the script noted in Part 1, you’ll need to deploy them. In order to do that, you can use the Deployment Templates built in to the ConfigMgr console. If you need to deploy to several collections at once (or with slightly different settings), you’ll need to run through the deployment wizard multiple times. I’ve developed this script to help make that process a bit more efficient.

This script requires that the content for the update list specified be downloaded into a deployment package and that any EULAs have been accepted. Otherwise, it will produce errors.

The script creates output, so it should be run under CSCRIPT on the site server itself.

The script was written for a particular process, which you’ll want to modify for your environment. At the place where I work, we deploy updates initially to a “Dogfood” group that performs initial testing to ensure that the updates don’t cause bluescreens or other major havoc. The next phase sees the deployment to the “Tech” team (the whole IT department), followed by a deployment to the production workstations. We also have separate collections for production servers and for computers that represent the operating system image source. Because of that, there are several different groups where you’ll want to update the collection ID to match your environment.

Also, don’t forget to update the sitecode to the one for your environment.

The way the script works, you can combine several groups on the command line at once (for example, /D /S /I to deploy to Dogfood, Servers, and Image computers simultaneously). The script handles all of the deployment settings, so you don’t actually need deployment templates for this to work. I still recommend them for manual deployments or other one-offs so that you can remain consistent.

Save the following as DeployUpdates.wsf:

<job>
<runtime>
<description>
This script will create a deployment for the named Update List and
assign it to the specified target(s).

This script does NOT use the templates found in SCCM.  Any changes
needed to the template must be coded in the script.
</description>
<named name="L" type=string helpstring="Name of the update list" required=true />
<named name="D" type=simple helpstring="Deploy to DOGFOOD" />
<named name="I" type=simple helpstring="Deploy to IMAGE" />
<named name="S" type=simple helpstring="Deploy to SVR" />
<named name="T" type=simple helpstring="Deploy to TECH" />
<named name="W" type=simple helpstring="Deploy to WKS" />
</runtime>
<script language="VBScript">

Const DogfoodCollectionID = "***ID***"
Const DogfoodDeadline = -1
Const DogfoodNotify = False

Const ImageCollectionID = "***ID***"
Const ImageDeadline = -1
Const ImageNotify = True

Const SvrCollectionID = "***ID***"
Const SvrDeadline = 1
Const SvrNotify = True

Const TechCollectionID = "***ID***"
Const TechDeadline = -1
Const TechNotify = False

Const WksCollectionID = "***ID***"
Const WksDeadline = -1
Const WksNotify = False

Const SiteCode = "***"

'Get SCCM WMI Connection
Set SCCM = GetObject("winmgmts://./root/sms/site_" & SiteCode)
Set WMIDate = CreateObject("WbemScripting.SWbemDateTime")

'Check named arguments
Set aNamed = WScript.Arguments.Named
If Not aNamed.Exists("L") Then
	'Missing list
	WScript.Arguments.ShowUsage
	WScript.Quit 1
End If
If Not (aNamed.Exists("D") or aNamed.Exists("I") or aNamed.Exists("S") or aNamed.Exists("T") or aNamed.Exists("W")) Then
	'Missing target
	WScript.Arguments.ShowUsage
	WScript.Quit 1
End If

'See if the list exists
Set RS = SCCM.ExecQuery("select * from SMS_AuthorizationList where LocalizedDisplayName='" & aNamed("L") & "'")
If RS.Count = 0 Then
	WScript.Echo "The Update List " & aNamed("L") & " cannot be found.  Please check spelling."
	WScript.Quit 1
End If

'Get the corrected name so that letter case matches what is visible to the user
For Each AL in RS
	Set lbAL = SCCM.Get("SMS_AuthorizationList.CI_ID=" & AL.CI_ID)
	UpdateListName = lbAL.LocalizedDisplayName
	UpdateArray = lbAL.Updates
Next
WScript.Echo "Creating deployments for " & UpdateListName
WScript.Echo "This deployment will be for " & UBound(UpdateArray)+1 & " update(s)"

'Create the deployments requested
If aNamed.Exists("D") Then AddDeployment " to DOGFOOD", DogfoodCollectionID, DogfoodDeadline, DogfoodNotify
If aNamed.Exists("I") Then AddDeployment " to IMAGE", ImageCollectionID, ImageDeadline, ImageNotify
If aNamed.Exists("S") Then AddDeployment " to SVR", SvrCollectionID, SvrDeadline, SvrNotify
If aNamed.Exists("T") Then AddDeployment " to TECH", TechCollectionID, TechDeadline, TechNotify
If aNamed.Exists("W") Then AddDeployment " to WKS", WksCollectionID, WksDeadline, WksNotify

Sub AddDeployment(NameSuffix, TargetCollectionID, SetDeadline, NotifyUser)
	WScript.Echo "Adding deployment" & NameSuffix
	Set UA = SCCM.Get("SMS_UpdatesAssignment").SpawnInstance_

	UA.ApplyToSubTargets = False
	UA.AssignedCIs = UpdateArray
	UA.AssignmentAction = 2		'This will apply the updates (not just detect them)
	UA.AssignmentDescription = ""
	UA.AssignmentName = UpdateListName & NameSuffix
	UA.DesiredConfigType = 1	'Updates are REQUIRED
	UA.DPLocality = 80			'Download from local and remote distribution points
	UA.LocaleID = 1033			'English
	UA.LogComplianceToWinEvent = True
	UA.NotifyUser = NotifyUser
	UA.OverrideServiceWindows = False
	UA.RaiseMomAlertsOnFailure = False
	UA.ReadOnly = False
	UA.RebootOutsideOfServiceWindows = False
	UA.SendDetailedNonComplianceStatus = True
	If SetDeadline >= 0 Then
		WMIDate.SetVarDate DateAdd("h",SetDeadline,Now())
		WMIDate.UTCSpecified = False
		UA.EnforcementDeadline = WMIDate.Value
	End If
	WMIDate.SetVarDate(Now())
	WMIDate.UTCSpecified = False
	UA.StartTime = WMIDate.Value
	UA.SuppressReboot = 0
	UA.TargetCollectionID = TargetCollectionID
	UA.UseGMTTimes = False

	UA.Put_
End Sub

</script>
</job>