How to edit ConfigMgr packages - update on schedule

3 minutes read

A few days back I asked for some ideas about what you need to get automated / scripted inside of Microsoft ConfigMgr and I actually got some nice feedback on that.

One of that was from a colleague of mine at sepago who needs to update packages on a distribution point by a daily schedule. I believe the package source gets updated daily and so they need to update the distribution point every night.

Update Distribution Points on a schedule

Get SMS_Package

The option I’m talking about is found in the package’s properties on the “Data Source” tab and is called “Update distribution points on a schedule”.

By default this option is disabled, which makes sense! You don’t want to enable this option for every package.

This option is represented by a WMI property of the SMS_Package class and it’s called RefreshSchedule.

By having a look at http://msdn.microsoft.com/en-us/library/cc144959.aspx we can see that RefreshSchedule is from the type SMS_ScheduleToken and it’s lazy. (Here I describe what lazy WMI properties are: http://www.david-obrien.net/2012/12/02/create-a-new-software-update-group-in-configmgr/)

SMS package SMS package

   So in order to access this property we'll have to make a direct reference to this WMI instance and we can then see a bit more, at least we can if someone has manually configured that above option or you already ran my script 😉

Create a SMS_ScheduleToken and apply it

We now know that we need to create an object from the class SMS_ScheduleToken and need to apply it to our SMS_Package object. Easily done. I already had a function to create that ScheduleToken. In this example I create a ScheduleToken which will create a schedule which runs every night at midnight from “today” on. Unfortunately the script can’t be as flexible as the GUI, so I kind of had to hard-code it into the script.

To furthermore get something like a mass configuration going I’m doing this configuration on a “per-folder” base. You tell the script that you want to configure ALL packages inside a folder with this option and the script will do so. If you rather want to do it on a “per-package” base then the script should give you an idea of how to do it.

This is how it looks like after the script ran:

package properties

Execute the script like that:

.\set-UpdatePkgOnDPBySchedule.ps1 -SMSProvider %NameOfSMSProvider% -FolderName %FolderWithPackages% -verbose

Download the script on codeplex: https://davidobrien.codeplex.com/SourceControl/latest#set-UpdatePkgOnDPBySchedule.ps1

All feedback welcome and asked for :)

Here’s the script:

#
.SYNOPSIS
    Script to set the "Update Distribution Point on a schedule" option for every package in a folder to "occur every night at 12PM"
.DESCRIPTION
    Script to set the "Update Distribution Point on a schedule" option for every package in a folder to "occur every night at 12PM"
.PARAMETER SMSProvider
    Hostname or FQDN of a SMSProvider in the Hierarchy
    This parameter is mandatory!
    This parameter has an alias of SMS.
.PARAMETER FolderName
    This parameter expects the name to the folder UNDER which you want to configure ALL packages.
    This parameter is mandatory!
    This parameter has an alias of FN.
.EXAMPLE
    PS C:\PSScript > .\set-UpdatePkgOnDPBySchedule.ps1 -SMSProvider cm12 -FolderName test -verbose

    This will use CM12 as SMS Provider.
    This will use "Test" as the folder in which you want all packages to get edited.
    Will give you some verbose output.
.INPUTS
    None.  You cannot pipe objects to this script.
.OUTPUTS
    No objects are output from this script.  This script creates a Word document.
.LINK
    http://www.david-obrien.net
.NOTES
    NAME: set-UpdatePkgOnDPBySchedule.ps1
    VERSION: 1.0
    
    LASTEDIT: July 23, 2013
    Change history:
.REMARKS
    To see the examples, type: "Get-Help .\set-UpdatePkgOnDPBySchedule.ps1 -examples".
    For more information, type: "Get-Help .\set-UpdatePkgOnDPBySchedule.ps1 -detailed".
    This script will only work with Powershell 3.0.

[CmdletBinding( SupportsShouldProcess = $False, ConfirmImpact = "None", DefaultParameterSetName = "" )]

param(
    [parameter(
    Position = 1,
    Mandatory=$true )
    ]
    [Alias("SMS")]
    [ValidateNotNullOrEmpty()]
    [string]$SMSProvider = "",

    [parameter(
    Position = 2,
    Mandatory=$true )
    ]
    [Alias("FN")]
    [ValidateNotNullOrEmpty()]
    [string]$FolderName = ""
)

Function Get-SiteCode
{
    $wqlQuery = “SELECT * FROM SMS_ProviderLocation”
    $a = Get-WmiObject -Query $wqlQuery -Namespace “root\sms” -ComputerName $SMSProvider
    $a | ForEach-Object {
        if($_.ProviderForLocalSite)
            {
                $script:SiteCode = $_.SiteCode
            }
    }
return $SiteCode
}

Function Convert-NormalDateToConfigMgrDate {
    [CmdletBinding()]
    param (
        [parameter(Mandatory=$true, ValueFromPipeline=$true)]
        [string]$starttime
    )

    return [System.Management.ManagementDateTimeconverter]::ToDMTFDateTime($starttime)
}

Function create-ScheduleToken {

$SMS_ST_RecurInterval = "SMS_ST_RecurInterval"
$class_SMS_ST_RecurInterval = [wmiclass]""
$class_SMS_ST_RecurInterval.psbase.Path ="\\$($SMSProvider)\ROOT\SMS\Site_$($SiteCode):$($SMS_ST_RecurInterval)"

$script:scheduleToken = $class_SMS_ST_RecurInterval.CreateInstance()
    if($scheduleToken)
        {
        $scheduleToken.DayDuration = 0
        $scheduleToken.DaySpan = 1
        $scheduleToken.HourDuration = 0
        $scheduleToken.HourSpan = 0
        $scheduleToken.IsGMT = $false
        $scheduleToken.MinuteDuration = 0
        $scheduleToken.MinuteSpan = 0
        $scheduleToken.StartTime = (Convert-NormalDateToConfigMgrDate $startTime)
        }
}

[datetime]$startTime = [datetime]::Today

$SiteCode = Get-SiteCode

create-ScheduleToken

$FolderID = (Get-WmiObject -Class SMS_ObjectContainerNode -Namespace "root\SMS\site_$($SiteCode)" -ComputerName $SMSProvider -Filter "Name = '$($FolderName)'").ContainerNodeID
$Packages = (Get-WmiObject -Class SMS_ObjectContainerItem -Namespace "root\SMS\site_$($SiteCode)" -ComputerName $SMSProvider -Filter "ContainerNodeID = '$($FolderID)'").InstanceKey

foreach ($Pkg in $Packages)
    {
        try
            {
                $Pkg = Get-WmiObject -Class SMS_Package -Namespace root\sms\site_$SiteCode -ComputerName $SMSProvider -Filter "PackageID ='$($Pkg)'"
                $Pkg = [wmi]$Pkg.__PATH
                $Pkg.RefreshSchedule = $scheduletoken
                $Pkg.put() | Out-Null
                Write-Verbose "Successfully edited package $($Pkg.Name)."
            }
        catch
            {
                Write-Verbose "$($Pkg.Name) could not be edited."
            }
    }

Updated:

Leave a Comment