Force SCCM Distribution Point to refresh failed packages
If a Distribution Point in System Center Configuration Manager has failed packages it probably has a cause and resending the packages might not be the right solution to the problem.
But I had the need to resend all failed packages on a distribution point and I was in no mood to click around in the GUI so I investigated the WMI classes listed on MSDN: http://msdn.microsoft.com/en-us/library/hh949540.aspx
First of all, what I am looking for is packages on a certain distribution point. These are listed in the class SMS_PackageStatusDistPointsSummarizer documented here: http://msdn.microsoft.com/en-us/library/hh949126.aspx
The class has a Property called State with the following states available:
1 |
2 |
3 |
4 |
5 |
6 |
For starters I filtered the packages after Status being 2 or 3 but there is no obvious property containing the name of the Distribution Point, only the property ServerNALPath.
After some more digging on MSDN I found the WMI class SMS_DistributionPointInfo which can be used to retrieve the Name and the ServerNALPath for a distribution point. WIN!
So for starters, get the Distribution Point info:
$Query = "Select NALPath,Name From SMS_DistributionPointInfo Where ServerName Like '%$DistPoint%'" $DistributionPoint = @(Get-WmiObject -Namespace "rootSMSSite_$SiteCode" -Query $Query) $ServerNalPath = $DistributionPoint.NALPath
On the first row I use the operator ‘Like’ which in WQL supports wildcarding by using “%” and regex-like syntax (more on that to come).
On the second row I use a trick to return the result in an array, that is what the @() is all about. This way I get the property Count on $DistributionPoint even if the query only returns one item.
Then I need to find all failed or retrying packages in that DistributionPoint. First I tried something like this:
$Query = "Select PackageID From SMS_PackageStatusDistPointsSummarizer Where ServerNALPath Like '$ServerNALPath' AND (State = 2 OR state = 3)" $FailedPackages = Get-WmiObject -Namespace "rootSMSSite_$SiteCode" -Query $Query
But wait, that gives me an Error stating:
Get-WmiObject : Invalid query “Select PackageID From SMS_PackageStatusDistPointsSummarizer Where ServerNALPath Like ‘[“Display=\SERVER01.
lab.lcl”]MSWNET:[“SMS_SITE=S01″]\SERVER01.lab.lcl’ AND (State = 2 OR state = 3)”
At line:1 char:23
+ $FailedPackages = Get-WmiObject -Namespace “rootSMSSite_$SiteCode” -Query …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Problem is that the ServerNALPath Contains brackets “[]” which tells WQL to look for one of the chars between the brackets and that won’t find what I want. The solution to this is to surround the [-char with brackets like this: “[[]” telling WQL to look for any on the chars “[“, which is just one char. Since the opening bracket wont be interpreted by WQL the closing bracket “]” will also be ignored. The next problem is that backslash “” is an escape character telling WQL that the next character should be interpreted literally and not as a special character, meaning that \ will translate to only . To solve this we’ll also have to escape each with a .
Both of these operations is easily done in PowerShell by using the replace operator on the $ServerNalPath:
$ServerNalPath = $DistributionPoint.NALPath -replace “([[])”,’[$1]’ -replace “()”,’$1′
This will make my $ServerNalPath look like this:
[[]”Display=\SERVER01.lab.lcl”]MSWNET:[[]”SMS_SITE=S01″]\SERVER01.lab.lcl
This looks a bit strange, but it will make my query execute without errors. Now I just have to loop through each of the failed packages and set the property “RefreshNow” to True and call the method Put to apply my new setting:
Foreach($Package in $FailedPackages) { $Query = "Select * From SMS_DistributionPoint WHERE SiteCode='$SiteCode' AND ServerNALPath Like '$ServerNALPath' AND PackageID = '$($Package.PackageID)'" $DistPointPkg = Get-WmiObject -Namespace "rootSMSSite_$SiteCode" -Query $Query Write-Verbose -Message "Refreshing package $($DistPointPkg.PackageID) on $($DistributionPoint.Name)" $DistPointPkg.RefreshNow = $true [Void]$DistPointPkg.Put() }
This will tell System Center Configuration Manager that the packages should be refreshed now.
For your convenience I’ve posted the script on TechNet Gallery:
http://gallery.technet.microsoft.com/Force-SCCM-Distribution-5c243aee