Last week I read a forum question about downloading updates in a software update group. I thought that I could create an easy example, but it wasn’t all as easy as I thought it would. As there is no cmdlet available that performs this specific action, I went back to WMI. In WMI there is a method AddUpdateContent in the SMS_SoftwareUpdatesPackage that should do the trick. After playing around with it for a while I noticed that this method is not as straight-forward as it looks.
The main problem I had with this method, was the documentation, or better, the lack of documentation. The SDK only contains a very old example that also doesn’t seem to use the right order for the parameters. Let’s start with what the parameters should be and walkthrough them in the order that they should be used:
- A boolean to indicate whether or not the content has to be replicated to the distribution points.
- An array that contains the IDs of the content that has to be added to the deployment package.
- An array that contains the source path where the content files are located.
- Note: The content of the updates have to be downloaded to a local, or network path already.
With these three parameters, it is possible to invoke the AddUpdateContent method, of the SMS_SoftwareUpdatesPackage class on a specific PackageID. An easy way to do that would be invoking the method on the WMI object path to the specific deployment package. This makes the following example:
Invoke-WmiMethod -Path "\\$($SiteServer)\root\sms\site_$($SiteCode):` SMS_SoftwareUpdatesPackage.PackageID='$PackageID'" ` -Name AddUpdateContent ` -ArgumentList @($false,$UpdateContentIDs,$UpdateContentSourcePaths)
To use this method it’s necessary to fill those parameters and to do that it’s necessary to collect some information. As I don’t think it’s very user-friendly to supply a CI ID as a function parameter, I will first search the CI ID of the software update group based on its display name in the SMS_AuthorizationList class.
$UpdateGroupCIID = (Get-WmiObject -Namespace root/SMS/site_$($SiteCode)` -ComputerName $SiteServer -Query "SELECT * FROM SMS_AuthorizationList ` WHERE LocalizedDisplayName='$SoftwareUpdateGroup'").CI_ID
With that CI ID I can find the software updates that are a member of the software update group. The easiest way to do that is to “join” the SMS_CIRelation class with the SMS_SoftwareUpdate class. This will provide a list with all the software updates that are a member of the specific software update group (a big thanks here to the SMSProv.log for providing me with the main part of the query).
$Updates = Get-WmiObject -Namespace root/SMS/site_$($SiteCode) ` -ComputerName $SiteServer -Query "SELECT upd.* FROM SMS_SoftwareUpdate` upd, SMS_CIRelation cr WHERE cr.FromCIID='$UpdateGroupCIID' AND` cr.RelationType=1 AND upd.IsContentProvisioned=0 AND upd.CI_ID=cr.ToCIID"
After finding the updates we can use the CI ID of the updates to find the associated content information. To get this information the easiest and quickest way is to use a “join” again, but this time between the SMS_CIToContent class and the SMS_CIContentFiles class. This will provide a list with the source locations of the software updates.
$UpdateContent = Get-WmiObject -Namespace root/SMS/site_$($SiteCode) ` -ComputerName $SiteServer -Query "SELECT fil.* FROM SMS_CIToContent ` con, SMS_CIContentFiles fil WHERE con.CI_ID='$UpdateCIID' AND ` con.ContentID=fil.ContentID"
The content IDs can now be used to fill the first array of the AddUpdateContent method. The second array has to be filled with the location to were the content IDs are downloaded. The complete script including the missing, and not explained, little bits-and-pieces and including a download function is available via the TechNet Galleries.
>> The complete script is available via download here on the TechNet Galleries! <<
Download the complete script and run it with a command line like .\Add-UpdateToPackage.ps1 <DeploymentPackage> <SoftwareUpdateGroup> <SiteCode> <SiteServer>. After the script starts the AddUpdateContent method the result can be followed in the SMSProv.log.
17 thoughts on “Add Update Content to a Deployment Package via PowerShell in ConfigMgr 2012”
This is great stuff, but is there a way in powershell to do the initial download of the software updates to a deployment package?
You might be able to use the network location of the deployment package as the download location, but I’m not sure how that WMI method will react on that (haven’t tested it). As the AddUpdateContent method will also copy it to that folder again.
After further review, what you have hits the nail on the head. One variation would be to use BITS to do the download. Excellent post Peter!
Thanks Peter !
Your ConfigMgr posts with PowerShell are awesome.
Working on automating the Patching process and this serves what I was looking for.
P.S. – Will use BITS to download the patches as suggested by Jim 🙂
Let me know the results of the BITS download.
Tried the Bits cmdlets to download this and it does work for me:
Start-BitsTransfer -Source $UpdateContent .SourceURL -Destination “C:\temp\$($UpdateContent .filename)”
Needs a little more work..!
Finally blogged about this and your post helped me a lot.
Let me know what you think:
How can we know which software update group corresponds to deployment package.
In my org different people created software update group and many times they mismatch the deployment package, ideally we follow the practice of have software update groups and deployment packages name as same.
can you help me on this,
You might want to take a look at this small tool: https://www.petervanderwoude.nl/post/new-tool-show-memberships-of-software-updates-to-deployment-packages-and-software-update-groups/
I was looking into this but you can also use the cmdlet Save-CMSoftwareUpdate. It is supersimple.
Save-CMSoftwareUpdate -SoftwareUpdateGroup $(Get-CMSoftwareUpdateGroup -Name $SUGName) -DeploymentPackageName $deplPkgName
This will download all sources into the package source location of the deploymentpackage.
Thank you for the feedback, Mike! You’re correct with the latest cmdlets the ability to download software updates has been added.
Yes, this new cmdlet simplified the download and add process significantly. In our process we do this and create a new package each month to provide some granularity in maintenance of packages when updates are superseded or expired. The one thing I have outstanding to update this process is to add the package to a deployment group for distribution. Still have to use the WMI commands to get this done. I wait until all the updates have been downloaded to the package and then add the package to the deployment group to avoid multiple tries as updates are being added to the package.
Works like a charm.
Thanks for the feedback, Jim!