How To: Initiate the “Validate” Action on all DPs for a Package in ConfigMgr 2012

ConfigMgr 2012 has a feature that allows you to validate content of a distribution point on a schedule, which works great for normal business. However, if you encounter an issue on a package and need to validate content immediately for each DP, it does require a bit of effort, as you have to go to the object in question, view the properties, then on the Content Locations tab, select a DP and click “Validate” – rinse and repeat–you must do this for each DP  to validate content, as described in the documentation. This post will describe how to enable a right-click option on any content in the Monitoring tab of the admin console.

validatecontent_2

You can download the .zip file and follow the directions in the included ‘info.txt’ file for a fast deployment to your admin console. You can review additional details below.

First you must create the proper r-click context menu. Copy the following .xml, save it as “ValidateContent.xml”, and copy it to C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\XmlStorage\Extensions\Actions\14214306-59f0-46cf-b453-a649f2a249e1\ValidateContent.xml. (Adjust the path as appropriate to your ConfigMgr Admin Console installation path).

<ActionDescription DisplayName="Validate Content on All DPs" MnemonicDisplayName="Validate Content on All DPs" Description = "Validate Content on All DPs" RibbonDisplayType="TextAndSmallImage">
<ShowOn>
<string>ContextMenu</string>
<string>DefaultHomeTab</string>
</ShowOn>
<Executable>
<FilePath>PowerShell.exe</FilePath>
-ExecutionPolicy RemoteSigned -File C:\PowerShell\CM12RClickTools\ValidatePackage.ps1 "##SUB:__Server##" "##SUB:__Namespace##" "##SUB:PackageID##"
</Executable>
</ActionDescription>

Notice in the .xml we specify the -ExeuctionPolicy RemoteSigned parameter. Best practice would be to sign your scripts, but if that’s not something you can manage easily, you can use the parameter as shown to modify the execution policy for the specific instance you’re launching, instead of changing the execution policy for all script execution. Next, copy the PowerShell code below, and save it to C:\PowerShell\CM12RClickTools\ValidatePackage.ps1 (although it’s named ValidatePackage, it does work for all content–Application, OS Image, Package, etc).

#capturing arguments:
$SiteServer = $args[0]
$SiteNamespace = $args[1]
$SiteCode = ($args[1]).Substring(14)
$PackageID = $args[2]

"{0} {1} {2} {3}" -f $SiteServer, $SiteNamespace, $SiteCode, $PackageID

$myFilter = "PackageID='$PackageID'"

$dps = gwmi sms_distributionpoint -namespace $SiteNamespace -ComputerName $SiteServer -filter $myFilter

if (($dps | measure-object).Count -ge 1) {
$dps | % {
"Initiating 'Validate Content' on {0}..." -f $_.ServerNALPath
if ($env:Computername -eq $SiteServer) {  #if running directly on the site server, omit the -computername argument

invoke-cimmethod -ClassName sms_distributionPoint -namespace $SiteNamespace -methodname "VerifyPackage" -arguments @{ PackageID=$_.PackageID; Nalpath=$_.ServerNALPath}
}
else {
invoke-cimmethod -ClassName sms_distributionPoint -namespace $SiteNamespace -ComputerName $SiteServer -methodname "VerifyPackage" -arguments @{ PackageID=$_.PackageID; Nalpath=$_.ServerNALPath}
}
}
"Validation initiated - Review Content Status for more information."
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

}
else {
"0 DPs found with this package. Content must be distributed in order to validate."
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

}

Now re-launch your ConfigMgr Admin console to use the new r-click->Validate Content on All DPs feature. As you can see from the code, this scritpt uses WMI, as SP1 does not contain cmdlets to perform this action. We use the Get-WMIobject (gwmi) cmdlet for the SMS_DistributionPoint class, filtered to only receive DPs for the desired PackageID. We then execute the VerifyPackage method for each DP.

**Important note: As of ConfigMgr 2012 SP1, only content in the content library (single instance store) will be validated. There is currently no ability to verify content on a package share (e.g. \\mydp\smspkgd$\CAS00023\).

For more information about Content Validation:

Happy Scripting!

Greg
ramseyg@hotmail.com

How To: Send Content to DP Group from Monitoring Node in ConfigMgr 2012 SP1

This post will demonstrate how to create a right-click action on the Monitoring->Distribution Status->Content Status tab to send content to a DP group. Sometimes when troubleshooting an issue, I realize that the content was sent to one DP for testing, and then promoted to production. The out-of-box experience requires you navigate back to the object (package, software update, application, etc) and then send content to DPs. This right-click tool will save you several clicks.

sendtodpgroup

After selecting to “Send to DP Group”, you will see a PowerShell window with a prompt to choose the desired DP Group.

sendtodpgroup-2

Of course, you could create multiple right-click items with hard coded DP Groups and actions, but for this post, we’ll use the dynamic selector shown above.

You can download the .zip file and follow the directions in the included ‘info.txt’ file for a fast deployment to your admin console. You can review additional details below.

First you must create the proper r-click context menu. Copy the following .xml, save it as “SendToDPGroup.xml”, and copy it to C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\XmlStorage\Extensions\Actions\14214306-59f0-46cf-b453-a649f2a249e1\SendToDPGroup.xml. (Adjust the path as appropriate to your ConfigMgr Admin Console installation path).

<ActionDescription DisplayName="Send to DP Group" MnemonicDisplayName="Send to DP Group" Description = "Send package to a DP group." RibbonDisplayType="TextAndSmallImage">
<ShowOn>
<string>ContextMenu</string>
<string>DefaultHomeTab</string>
</ShowOn>
<Executable>
<FilePath>PowerShell.exe</FilePath>
-ExecutionPolicy RemoteSigned -File C:\PowerShell\CM12RClickTools\SendToDPGroup.ps1 "##SUB:__Server##" "##SUB:__Namespace##" "##SUB:PackageID##" "##SUB:ObjectTypeID##" "##SUB:SoftwareName##"
</Executable>
</ActionDescription>

Notice in the .xml we specify the -ExeuctionPolicy RemoteSigned parameter. Best practice would be to sign your scripts, but if that’s not something you can manage easily, you can use the parameter as shown to modify the execution policy for the specific instance you’re launching, instead of changing the execution policy for all script execution. Next, copy the PowerShell code below, and save it to C:\PowerShell\CM12RClickTools\SendToDPGroup.ps1

#capturing arguments:
$SiteServer = $args[0]
$SiteNamespace = $args[1]
$SiteCode = ($args[1]).Substring(14)
$PackageID = $args[2]
$objectTypeID = $args[3]
$SoftwareName = $args[4]
$SiteDrive = $sitecode + ":"

"{0} {1} {2} {3} {4} {5}" -f $SiteServer, $SiteNamespace, $SiteCode, $PackageID, $objectTypeID, $SoftwareName

#Connect to PowerShell Provider:
$ModulePath = (($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) + '\ConfigurationManager.psd1'
"Connecting to the Provider..."
import-module $modulePath -force
if ((get-psdrive $siteCode -erroraction SilentlyContinue | measure).Count -ne 1) {
new-psdrive -Name $siteCode -PSProvider "AdminUI.PS.Provider\CMSite" -Root $SiteServer
}
cd $siteDrive

"Gathering DP Group Names..."
$intcounter = 1
#Create a hashtable
$DPgroups = @{0 = "Name"}
$DPgroups.Remove(0)
Get-CMDistributionPointGroup | select Name | sort Name | % {
$DPgroups += @{$intcounter = $_.Name}
$intcounter++
}

#Choose the DP group
$dpgroups.GetEnumerator() | Sort-Object name
$DPgroup = read-host "Select a DP group, by number and press [enter]"
$DPGroupName = $DPgroups.get_item([int]$DPgroup)

switch ($objectTypeID)
{
#ObjectTypeIDs from SMS_ObjectContentInfo WMI Class
2 {Start-CMContentDistribution -PackageID $PackageID -DistributionPointGroupName $DPGroupName}
14 {Start-CMContentDistribution -OperatingSystemInstallerID $PackageID -DistributionPointGroupName $DPGroupName}
18 {Start-CMContentDistribution -OperatingSystemImageID $PackageID -DistributionPointGroupName $DPGroupName}
19 {Start-CMContentDistribution -BootImageID $PackageID -DistributionPointGroupName $DPGroupName}
21 {"SMS_DeviceSettingPackage - Nothing to distribute here"}
23 {Start-CMContentDistribution -DriverPackageID $PackageID -DistributionPointGroupName $DPGroupName}
24 {Start-CMContentDistribution -DeploymentPackageID $PackageID -DistributionPointGroupName $DPGroupName}
31 {Start-CMContentDistribution -ApplicationName $SoftwareName -DistributionPointGroupName $DPGroupName}
}

"DP Group Targeted distributed-Use the Monitoring node to monitor DP status."

Write-Host "Complete. Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Now re-launch your ConfigMgr Admin console to use the new r-click->Send to DP Group feature. As you can see from the code, we use Get-CMDistributionPointGroup to obtain all DP groups, and then create a hash table to allow us to display a simple selector. We then use Start-CMContentDistribution to send the content to the desired DP Group. Notice the required argument is based on the object type (package, application, updates deployment package, etc.), so we use a simple switch statement to determine the appropriate parameters to run.

Happy Scripting!

Greg
ramseyg@hotmail.com