Using PowerShell to Rerun an SCCM Client Advertisement
I wrote the following function to rerun an advertisement on a remote client computer using either the AdvertisementID or the PackageID. Like all sample code found online, please run through a test environment first, and use at your own risk!
1<#
2
3*******************************************************************************************************************************
4** All code is for demonstration only and should be used at your own risk. I cannot accept liability for unexpected results. **
5*******************************************************************************************************************************
6
7Use: You're welcome to use, modify, and distribute this script. I'd love to hear about how you're using it or
8modifications you've made in the comments section of the original post over at ChristopherKibble.com.
9
10#>
11
12Function Start-CCMRerunAdvertisement {
13
14 <#
15 .SYNOPSIS
16 Restarts an SCCM advertisement on a remote computer.
17 .DESCRIPTION
18 This script will remotely connect to a computer running the CCM Client,
19 find an advertisement by the Advertisement ID or the Package ID (or
20 both), and then restart the advertisement.
21 .NOTES
22 File Name : Start-CCMRerunAdvertisement.ps1
23 Version : 2017-09-21 (v1.0)
24 Author : Christopher Kibble (www.ChristopherKibble.com)
25 Tested : PowerShell Version 5
26 .PARAMETER ComputerName
27 The name of the remote computer to connect to.
28 .PARAMETER AdvertisementID
29 All or part of the Advertisement ID to run. Wildcards accepted.
30 Defaults to *. Either this or PackageID must be specified.
31 .PARAMETER PackageID
32 All or part of the Package ID to run. Wildcards accepted.
33 Defaults to *. Either this or AdvertisementID must be specified.
34 .PARAMETER MaxRun
35 If more than one advertisement meets your criteria, how many of the
36 advertisements to run. Defaults to 1.
37 .PARAMETER MoreThanPing
38 In environments where ICMP may not allow pinging a remote computer,
39 this switch will make the script attempt to connect to C$ on the remote
40 computer in order to determine if it's online.
41 .EXAMPLE
42 Start-CCMRerunAdvertisement -ComputerName SANDIAGO-001 -AdvertisementID "US000001"
43 #>
44
45 [CmdLetBinding()]Param(
46 [Parameter(Mandatory=$true)][string]$computerName,
47 [Parameter(Mandatory=$false)][string]$advertisementId = "*",
48 [Parameter(Mandatory=$false)][string]$packageId = "*",
49 [Parameter(Mandatory=$false)][int]$maxRun = 1,
50 [Parameters(Mandatory=$false)][switch]$moreThanPing = $false
51 )
52
53 # TODO LIST:
54 #
55 # - Better error control when WMI connections fail.
56 # - Are we using the best method to sort when using MaxRun?
57 #
58
59 if($advertisementId -eq "*" -and $packageId -eq "*") {
60 Write-Error "You must supply either an AdvertisementID or a PackageID"
61 return "Missing Parameters"
62 break
63 }
64
65 $searchString = "$advertisementId-$packageId-*"
66
67 if(!(Test-Connection -ComputerName $computername -ErrorAction SilentlyContinue)) {
68
69 if($moreThanPing) {
70 if(!(Get-ChildItem "\\$computername\c$" -ErrorAction SilentlyContinue)) {
71 Write-Error "System Offline"
72 Return "System Offline"
73 break
74 }
75 } else {
76 Return "System Offline"
77 break
78 }
79
80 }
81
82 Write-Verbose "Getting ID of ScheduleMessage on $computername"
83
84 $schMsgs = Get-WmiObject -ComputerName $computername -Namespace "root\ccm\policy\machine\actualconfig" -Class CCM_Scheduler_ScheduledMessage
85
86 $thisMsg = $schMsgs | ? { $_.ScheduledMessageID -like $searchString } | Sort ActiveTime -Descending | select -First $maxRun
87
88 if(!$thisMsg) {
89 Write-Verbose "Cannot Find Advertisement/Package on Target Computer"
90 Return "Cannot Find Advertisment"
91 break
92 }
93
94 $thisMsg | % {
95
96 [xml]$activeMessage = $_.activeMessage
97
98 $amProgramId = $activeMessage.SoftwareDeploymentMessage.ProgramID
99 $amAdvId = $activeMessage.SoftwareDeploymentMessage.AdvertisementID
100 $amPkgId = $activeMessage.SoftwareDeploymentMessage.PackageID
101 $ScheduledMessageId = $_.ScheduledMessageId
102
103 Write-Verbose "Restarting $amArogramId (ADV=$amAdvId) (PKG=$amPkgId) for Schedule Message $ScheduledMessageId"
104
105 $softwareDist = Get-WmiObject -ComputerName $computername -Namespace "root\ccm\policy\machine\actualconfig" -Class CCM_SoftwareDistribution -Filter "ADV_AdvertisementID = '$amAdvId' and PKG_PackageID = '$amPkgId'"
106
107 $original_Rerun = $softwareDist.ADV_RepeatRunBehavior
108
109 if($original_Rerun -ne "RerunAlways") {
110 write-verbose "Changing Rerun Status from $original_Rerun to RerunAlways"
111 $softwareDist.ADV_RepeatRunBehavior = "RerunAlways"
112 $softwareDist.put() | Out-Null
113 }
114
115 Write-Verbose "Triggering Schedule on $computername"
116 Invoke-WmiMethod -ComputerName $computername -Namespace "root\ccm" -Class "SMS_CLIENT" -Name TriggerSchedule $ScheduledMessageId | Out-Null
117
118 Write-Verbose "Sleeping for 5 seconds"
119 Start-Sleep -Seconds 5
120
121 if($original_Rerun -ne "RerunAlways") {
122 Write-Verbose "Changing Rerun Status back to $original_Rerun"
123 $softwareDist.ADV_RepeatRunBehavior = "$original_Rerun"
124 $softwareDist.put() | Out-Null
125 }
126
127 Return "Reran Advertisement"
128
129 }
130
131}
5 comments
Going to test this today, just curios what happens when I rerun a package that has several programs deployed (an install line and uninstall line) will it run the install then the uninstall afterwoods? or can you specify which program ID to run?
Great question, Nat! Right now it'd run all of them but what a great idea for an improvement!
Great script. How long until the advertisement begins to run? Does App deployment need to run to kick off the updated trigger schedule?
Hey Justin, thanks! The advertisement will begin immediately if it'll run from the DP or is already in the cache, otherwise it'll run after it's re-cached. Since it's an advertisement and not a deployment, App Deployment will not need to run. In other words, this is for packages/programs and not applications.
Thanks Chris, I can see this script being very useful.
i'm curious if there is a way to retrieve the names of the Distribution Points that are sent back to the client when it requests DPs from the MP. I have been digging through the various WMI classes and name spaces on the SCCM client, but I can't seem to find a way to do this via WMI or PowerShell.
Seems like the only way I have found to do this is to search through the LOG files.