Saturday, March 15, 2014

PowerShell + SCCM 2012 R2 : Client Push Installation

In this post, would share PowerShell way of enabling Client Push Installation on a Site . Divided into 3 Steps:

  1. Enable Client Push Installation
  2. Create Boundary Group, Add Boundary and set Content Location
  3. Distribute the Config Mgr Client Package

Enable Client Push Installation

After loading the ConfigurationManager PowerShell module, if we search for the commands with noun clientpush we get following output:
PS DEX:\> gcm -Noun *clientpush* -Module configurationmanager

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Get-CMClientPushInstallation                       configurationmanager
Cmdlet          Set-CMClientPushInstallation                       configurationmanager

Now one can go and read up help for these, I personally prefer the Online version of the help as it shows the Parameter sets and is always up to date too. How to do that ?
PS DEX:\> help Set-CMClientPushInstallation -Online

To enable the client push installation we will be using the cmdlet Set-CMClientPushInstallation (you would have guessed that by the Verb-Noun naming convention).

PS DEX:\> Set-CMClientPushInstallation -SiteCode DEX -EnableAutomaticClientPushInstallation $true -EnableSystemTypeServer $true -EnableSystemTypeWorkstation $true -EnableSystemTypeConfigurationManager $true -InstallClientToDomainController $true -ChosenAccount "Dexter\Administrator" -InstallationProperty "SMSSITECODE=DEX" -Verbose

Once the above cmdlet runs it will configure the settings. If you see the cmdlet and parameter names are very descriptive in what they are doing ....still thinking of getting starting with PowerShell in Config Mgr...It's easy ;)


The Client Push installation settings are done, but in order for us to make sure that the discovered clients are able to locate the content we need to create a Boundary group and specify the Server for content location under that.

Create Boundary Group, Add Boundary and set Content Location

Right now I have only one Boundary by the name of my AD Site and no Boundary groups as evident from below ScreenShot:

Let's create a new Boundary Group and add this Boundary to it and specify the content location under it.

#Before starting how to discover the cmdlets we will be using's simple but wanted to point out. (Get-Command is your friend here)

PS DEX:\> gcm -Noun *boundary*

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Add-CMBoundaryToGroup                              configurationmanager
Cmdlet          Get-CMBoundary                                     configurationmanager
Cmdlet          Get-CMBoundaryGroup                                configurationmanager
Cmdlet          New-CMBoundary                                     configurationmanager
Cmdlet          New-CMBoundaryGroup                                configurationmanager
Cmdlet          Remove-CMBoundary                                  configurationmanager
Cmdlet          Remove-CMBoundaryFromGroup                         configurationmanager
Cmdlet          Remove-CMBoundaryGroup                             configurationmanager
Cmdlet          Set-CMBoundary                                     configurationmanager
Cmdlet          Set-CMBoundaryGroup                                configurationmanager

#creating the Boundary group
PS DEX:\> New-CMBoundaryGroup -Name "DexLabBG" -Description "Boundary Group for my LAB" -DefaultSiteCode DEX -Verbose
VERBOSE: Performing the operation "New" on target "BoundaryGroup: New".

CreatedBy       : DEXTER\Administrator
CreatedOn       : 3/14/2014 8:21:13 AM
DefaultSiteCode : DEX
Description     : Boundary Group for my LAB
GroupID         : 16777217
MemberCount     : 0
ModifiedBy      : DEXTER\Administrator
ModifiedOn      : 3/14/2014 8:21:13 AM
Name            : DexLabBG
Shared          : False
SiteSystemCount : 0

#Now add the Boundary to the Boundary Group
PS DEX:\> Add-CMBoundaryToGroup -Boundary (Get-CMBoundary ) -BoundaryGroup (Get-CMBoundaryGroup ) -Verbose
VERBOSE: Performing the operation "Add" on target "BoundaryToGroup: Name="DexLabBG"".

Everything done till the important piece here is to specify the content location for the above Boundary group, so that clients falling under these Boundaries (part of Boundary group) know where to look for content.

If you look at the ConfigMgr cmdlets there is no cmdlet which does that for you....I though Set-CMBoundaryGroup would do that but it doesn't apparently.

ConfigMgr MVP Kaido was kind enough to mention in comments that there does exist a cmdlet to add a SiteSystem (DP) to the Boundary Group named Add-CMSiteSystemToBoundaryGroup. Do check out his awesome ConfigMgr and PowerShell Script Library at

Though I would be going for the WMI way of doing this action.

Let's search for a class which matches something like *Boundary*
 Get-CimClass -ClassName *boundary* -ComputerName dexsccm -Namespace root/SMS/Site_DEX -Verbose

Now the output of the cmdlet..take a not of the Computername and NameSpace params  which specify the remote SCCM server and the appropriate SMS namespace.

Try epxloring all the classes above and you will come to know that we are going to use SMS_BoundaryGroup class from the above ones.

Note - If you don't want to specify the ComputerName and NameSpace parameter and its agruments every time you use the CIM Cmdlets then you can use the $PSDefaultParameterValues like below :
$PSDefaultParameterValues =@{"get-cimclass:namespace"="Root\SMS\site_DEX";"get-cimclass:computername"="DexSCCM";"get-cimInstance:computername"="DexSCCM";"get-ciminstance:namespace"="Root\SMS\site_DEX"}

If we expand the Methods on the SMS_BoundaryGroup class we will see one which will pique your interest.

Let's give this method a Shot...But wait we need something called ServerNALPath that needs to be passed to the Method.

 How do we get that ?? Don't loose hope yet..with PowerShell v3 it becomes very easy to search WMI Classes based on a property name...see me do it now.

Note - I have setup the $PSDefaultParameterValues so now the Get-CIMClass & Get-CIMInstance cmdlet will by default take the param Computername and Namespace values.

#search for WMI classes with a specific property name
PS DEX:\> Get-CimClass -PropertyName ServerNALPath

   NameSpace: Root/SMS/site_DEX

CimClassName                        CimClassMethods      CimClassProperties
------------                        ---------------      ------------------
SMS_DistributionPoint               {VerifyPackage, C... {BitsEnabled, IsPeerDP, IsProtected, ISVData...}
SMS_AllDistributionPoint            {}                   {ObjectTypeID, PackageID, PackageType, SecureObjectID...}
SMS_BoundaryGroupSiteSystems        {}                   {Flags, GroupID, ServerNALPath, SiteCode}
SMS_PackageStatusDistPointsSumma... {}                   {LastCopied, PackageID, PackageType, SecuredTypeID...}
SMS_TaskSequenceReferenceDps        {}                   {Hash, PackageID, ServerNALPath, SiteCode...}
SMS_TaskSequenceAppReferenceDps     {}                   {Hash, PackageID, ServerNALPath, SiteCode...}

Awesome ..Now I get a feeling we need to work with SMS_DistributionPoint class to get the value for property ServerNALPath. So here we go....I have only one DP in my LAB.

PS DEX:\> Get-CimInstance -ClassName SMS_DistributionPoint | select -Property ServerNALPath -Unique


Easy right......You need to know all the moving parts to work with PowerShell and ConfigMgr (using WMI) and that is exactly the kind of understanding I was looking for ......Ok enough with my talk..moving further

Let's give the AddSiteSystem Method of SMS_BoundaryGroup a shot  now:
Note I got the flag from this Technet I took a guess by the class name that the DP I add will become an instance of the class SMS_boundaryGroupsitesystems . All set

PS DEX:\> $BoundaryGroup = Get-CimInstance -ClassName SMS_BoundaryGroup
PS DEX:\> Invoke-CimMethod -InputObject $BoundaryGroup -MethodName AddSiteSystem -Arguments @{ServerNALPath = [string[]]
'["Display=\\\"]MSWNET:["SMS_SITE=DEX"]\\\'; Flags=([System.UInt32[]]0) } -Verbose
VERBOSE: Performing the operation "Invoke-CimMethod: AddSiteSystem" on target "SMS_BoundaryGroup (GroupID = 16777217)".
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''instance' = SMS_BoundaryGroup (GroupID =
16777217),'methodName' = AddSiteSystem,'namespaceName' = root/sms/site_dex'.

                                                ReturnValue PSComputerName
                                                ----------- --------------
                                                          0 DexSCCM
VERBOSE: Operation 'Invoke CimMethod' complete. 

Voila that worked after few attempts. Would like to point out that based on the documentation of the class the arguments you pass to the method in above are type-cast to an array....If you have any doubts grasping that drop me a comment would take time to explain that.

So what we have achieved so far is evident from the Screenshots below:

#See the Boundary Group has a member Boundary added 

#See below that we now have the Content Location set for the Boundary group

Distribute the Config Mgr Client Package to the DP Group

Phewww!!! Now the last piece of Puzzle is to distribute the ConfigMgr Client Package to our DP Group.
#Distribute the Config Mgr Client Package to ensure that the Package resides there
Start-CMContentDistribution -PackageName "Configuration Manager Client Package" -DistributionPointGroupName "Dex LAB DP group"

Now we can see the changes reflect in the Console too.

In the above screenshot there is a way to  verify the integrity of the package on a Distribution Point. Let's do it using PowerShell ...the class which is of interest is SMS_DistributionPoint have a look at the methods on this one:
PS DEX:\> Get-CimClass -ClassName SMS_DistributionPoint |  Select -ExpandProperty Cimclassmethods

Name                                             ReturnType Parameters                    Qualifiers
----                                             ---------- ----------                    ----------
VerifyPackage                                        SInt32 {PackageId, NALPath}          {implemented, static}
CancelDistribution                                   SInt32 {PackageId, NALPath}          {implemented, static}

Note that the method exists on the SMS_DistributionPoint Class.
Look closely that we need NAL Path which can be found on the instance of the SMS_DistributionPoint (as every package that is stored in the DP is an instance of this class) so we are going to store it in a variable first and use it later.
PS DEX:\> $package = Get-CimInstance -ClassName SMS_DistributionPoint -Filter 'PackageID="DEX00002"'
PS DEX:\> Invoke-CimMethod -ClassName SMS_DistributionPoint -Name VerifyPackage -Arguments @{PackageID=$package.PackageI
D;NALPath=$package.ServerNALPath} -ComputerName dexsccm -Namespace root/sms/site_DEX -Verbose
VERBOSE: Performing the operation "Invoke-CimMethod: VerifyPackage" on target "SMS_DistributionPoint".
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = VerifyPackage,'className' =
SMS_DistributionPoint,'namespaceName' = root/sms/site_DEX'.

                                                ReturnValue PSComputerName
                                                ----------- --------------
                                                          0 dexsccm
VERBOSE: Operation 'Invoke CimMethod' complete.

Returns 0 which means the integrity is validated.

So that's it we have successfully configured Client Push settings in our Environment.

For all the code samples below is the gist:

Till next post