How to remotelly trigger run advertisement on SCCM 2012 Client

Hello Everybody,

there is many questions on the web about remote invoking SCCM actions on the client via scripting.
Within official SCCM 2012 SDK, there is absolutelly nothing about such client actions. Within the 2007 version it is demonstrated, but with local script and invoking the CPAppletMgr in conjuction with UIResourceMgr COM object class. But configuration of DCOM for accepting remote request for this objects is at least tricky and useless because it is dummy to beleve this classes will not change in the future.
Most natural way for SCCM to do this is create apropriative WMI calls.
And here Microsoft makes new troubles for all of us, scripting guys – in new SCCM 2012 SDK is dry description of classes witin CCM namespace. But also absolutelly nothing as notes for using this.
Finally I have found brilliant tool: SMSCLICTR, what encapsulates all of settings within simple to use .NET assemblies. This can also be used within Powershell, but sometimes usage such external modules is prohibited.
So I have made own piece of code in Powershell for doing this manually.

  1. First of all I had to enforce current Machine policy refresh. I is done by following function:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function ForceMachinePolicyRefresh
    {
    param($clientname, $username, $userpass, $PolicyID)
    $ms = new-object system.management.managementscope
    $ms.Path = "\\$clientname\root\CCM"
    $ms.options.username = $username
    $ms.options.password = $userpass
    $mc = new-object system.management.managementclass($ms, 'SMS_Client', $null)
    $mc.invokeMethod("TriggerSchedule", $PolicyID)
    return $mc
    }

    There are several things to explain within this code:

    • It connects to namespace with explicity manner, without any casting, because of credentials passing. This code can be invoked only remotelly, because setting $ms.options.username is supported only with remote connection.
    • It is general function for enforcing any scheduled action. So it can be used not only for Machine policy refresh, but also applying changes within localconfig, as you can see later.
    • Last thing connected with this small piece of code is fact it can be used as a base for manipulating any of published method within SMS_Client WMI class. Now the MS refrence from SDK can be helpfull.
  2. So, when we have this defined we can go further. Now the function for invoking exact advertisement of specified Package. Function takes all necessary arguments:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    function InvokeOptionalAdvertisement
    {
    Param($clientname, $username, $userpass, $advertID, $packID)
    $mc = ForceMachinePolicyRefresh -clientname $clientname -username $username -userpass $userpass -PolicyID "{00000000-0000-0000-0000-000000000021}"
    $ms = new-object system.management.managementscope
    $ms.path = "\\$clientname\root\ccm\policy\Machine\ActualConfig"
    $ms.options.username = $username
    $ms.options.userpass = $userpass
    $query =new-object System.Management.ObjectQuery
    $query.QueryString = "Select * From CCM_SoftwareDistribution where ADV_AdvertisementID = '$advertID' and PKG_PackageID = '$packID'"
    $searcher = new-object system.management.managementobjectsearcher($query)
    $searcher.Scope = $ms
    $advs = $searcher.Get
    $enum = $advs.GetEnumerator()
    $enum.MoveNext()
    $adv = $enum.Current
    $adv.SetPropertyValue("ADV_RepeatRunBehavior", "RerunAlways")
    $adv.SetPropertyValue("ADV_MandatoryAssignments", "True")
    $adv.Put()
    $query1 = new-object System.Management.ObjectQuery
    $query1.QueryString = "Select ScheduledMessageID FROM CCM_Scheduler_ScheduledMessageID like '" + $adv.ADV_AdvertisementID + "-" + $adv.PKG_PackageID + "%'"
    $searcher1 = new-object System.management.managementobjectsearcher($query1)
    $searcher1.scope = $ms
    $scheds = $searcher1.Get()
    $scheds | Foreach-Object { $mc[1].invokeMethod("TriggerSchedule", $_.ScheduledMessageID) }
    return $adv
    }

    So now a word of comment for this function:

    • On the beginning we invoke machine policy refresh with our previously defined function
    • Next we define new management scope with namespace of actual config, what is used by CCM.
    • After that we need the ObjectQuery instance for encapsulating correct WMI Query. This query select all CCM_SoftwareDistribution objects, what matches our conditions
    • by usage of searcher object we obtain all required object to $advs variable
    • trick with enumerator and him Current property gives us only one object, instead of containing it collection
    • now we do main Job. We modify two properties, what ensures that optional assigment is now mandatory and will run on next schedule of this Advertisement
    • last part of the script gets proper objects of schedulers for our Advertisement and Package.
    • finally we trigger the schedules and task sequence runs properly.