Force SCCM Distribution Point to refresh failed packages

Page content

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:

<td width="160">
  INSTALLED
</td>
<td width="160">
  INSTALL_PENDING
</td>
<td width="160">
  INSTALL_RETRYING
</td>
<td width="160">
  INSTALL_FAILED
</td>
<td width="160">
  REMOVAL_PENDING
</td>
<td width="160">
  REMOVAL_RETRYING
</td>
<td width="160">
  REMOVAL_FAILED
</td>
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&#8221;]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