Disabling Prestaged Content on SCCM Distribution Points With PowerShell

Author by Matt Herman

I recently worked with a customer to deploy a large number of Distribution Points (DPs).  We had good timing on the project, because the customer also was deploying new virtualization hosts at the same time.  This allowed us to create prestaged content and include in the VM templates sent on the hosts, so that the DPs did not need to sync that content over the WAN after they were built.  Once the prestaged content was loaded on the DP, we would disable prestaged content and the DP would sync future content normally.

This plan worked well and saved us days of syncing content over slow connections, but we ran into an issue.  We ended up generating and sending multiple versions of the prestaged content as the objects in SCCM changed.  On some DPs, we found packages with a distribution status of “waiting for prestaged content” even after prestaged content was disabled.  We used the following script to resolve this by redistributing packages with errors or that were “waiting for prestaged content” when we disabled prestaged content on each DP.

################################################################################
#
#
#  Name: DistributionPointConfig-DisablePrestagedContent.ps1
#
#  AUTHORS: Matt Herman & Aaron Fields
#  REFERENCE: This script uses code from David O'Brien, originally posted here: http://www.david-obrien.net/2013/11/20/redistribute-failed-packages-configmgr-dps/
#
#  VERSION HISTORY:
#
#  1.0 10/15/14 Initial Release

#
#################################################################################


#Modules
Import-Module "D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" -Force

# Global Variables   
$ScriptPath = ($MyInvocation.MyCommand.Path) | Split-Path
$SiteCode = "SITE_CODE"
$LOGFile = $ScriptPath +  "\Logs\DisablePrestaged2.txt"
        
#Enter SCCM PSProvider
Set-Location "SITE_CODE:\"

# Find all DPs based on naming convention.
$DPs = Get-CMDistributionPoint -SiteSystemServerName DP*.YourDomain.Com
   
#Enter loop for processing each DP
Foreach ($DP in $DPs) 
    {
       #Reformat the Distribution Point's name
       $DPName = $DP.NetworkOSPath.replace("\\", "")
                    
       #Check to see if Prestaged Content is enabled
       If ($DP.EmbeddedProperties.PreStagingAllowed.Value -eq 1)
      
       {
            #Disable Prestaged Content
            Set-CMDistributionPoint -SiteCode $SiteCode -SiteSystemServerName  $DPName -AllowPreStaging 0 -verbose
      
            #Redistribute Packages that are failed or "Waiting for Prestaged Content"
            $ServerName = $DPName

            $failures = $null
            # Find all content with State = 1, State = 2 or State = 3, see http://msdn.microsoft.com/en-us/library/cc143014.aspx
            #Added State = 7 for Waiting for Prestaged Content
            $failures = Get-WmiObject -Namespace root\sms\site_$SiteCode -Query "SELECT * FROM SMS_PackageStatusDistPointsSummarizer WHERE ServerNALPath like '%$ServerName%' and (State = 1 or State = 2 or State = 3 or State = 7)"
            if ($failures -eq $null)
                 {
                    "No failed content distribution."
                 }
            else
                {
                     foreach ($failure in $failures)
                        {
                             # Get the distribution points that content wouldn't distribute to
                    $DistributionPoints = Get-WmiObject -Namespace root\sms\site_$SiteCode -Query "SELECT * FROM SMS_DistributionPoint WHERE SiteCode='$($failure.SiteCode)' AND  PackageID='$($failure.PackageID)'"
                             foreach ($DistributionPoint in $DistributionPoints)
                                {
                                     #check if we are really looking at the correct Distribution Point
                        if ($DistributionPoint.ServerNALPath -eq $failure.ServerNALPath)
                                         {
                                            # Use the RefreshNow Property to "Refresh Distribution Point", see http://msdn.microsoft.com/en-us/library/hh949735.aspx
                             $DistributionPoint.RefreshNow = $true
                                             $DistributionPoint.put()
                                         }
                                }
                        }
                }
            Write-Output "Prestage Content Disabled and Content Redistribed on $DPName - $(Get-Date)" | Out-File $LOGFile -Append
        }
         ELSE {Write-Output "No Action taken on $DPName - $(Get-Date)" | Out-File $LOGFile -Append}
    } #End Foreach Loop

One note on using this script.  It will find and check all of the DPs in your SCCM site based on a naming convention.  You can use just * if you don’t have consistent naming, but it better to limit it if you can.  In any situation, it can take several minutes to build the array with all of the DPs, depending on the size of your environment.  Go ahead and let it run for a few minutes and then you should see it start to process the DPs.  As always, you can monitor the log file with CMTrace to see the progress.

Author

Matt Herman

Technical Architect