Using PowerShell to Rerun an SCCM Client Advertisement

Share on:

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

Nat

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?

Chris Kibble

Great question, Nat! Right now it'd run all of them but what a great idea for an improvement!

Justin

Great script. How long until the advertisement begins to run? Does App deployment need to run to kick off the updated trigger schedule?

Chris Kibble

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.

Jim McBee

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.