Scripted Deployment of Distribution Points in SCCM 2012 including rate scheduling

Somewhat quick and dirty, but I’m sure it’ll be of use to anyone doing a larger scale rollout of distribution points.

The following script can interactively roll out distribution points for you, saving a huge amount of clicking around in the SCCM console. The code can easily be adapted to run everything from functions and bulk import a list of distribution points from CSV to SCCM.

#Add distribution point with State Migration and Pulse Rate limitation and scheduling
#Author: Jos Lieben, OGD
#Copyright: Free to Use and Distribute
#Credits: David O’Brien ( for WMI class interaction
#notice: you must have the required console updates for some of these commands to work with SCCM 2012 SP1

#If you clear any config, the script will prompt you for it, config simply helps you simplify deployments if for example, you only have one site
#Path to your PSD files
Import-Module “C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1″
#Your site code
$site_code = “EU1″
#Name of your distribution point (Fully Qualified Name required!)
$server_name = “”
#Drive letter for your primary content library, use Automatic if you wish SCCM to manage this for you
$driveletter_plibrary = “”
#Drive letter for your primary content share, use Automatic if you wish SCCM to manage this for you
$driveletter_pshare = “”
#If you wish to add a state migration point to the DP, set this to $true
$add_statemigrationpoint = $false
#Path to data on the state migration point
$state_migrationpoint_localpath = “”
#Distribution Point Group Membership can be configured with this variable
$distributionpointgroup = “”
#Set to False if you do not wish to configure transfer schedules for your DP ($false recommended)
$add_schedule = $true
#size of each block sent, leave at 0 to prompt, only used when add_schedule=$true
$block_size = 0
#delay between each block sent, leave at 0 to prompt, only used when add_schedule=$true
$block_delay = 0
#Array containing 24 elements, one for each hour of the day. This property specifies the type of usage for each hour.
# 1 means all Priorities, 2 means all but low, 3 is high only, 4 means none
#this example allows only high priority sendings from monday till friday between 8AM and 8PM and everything outside that timeframe
$HourUsageScheduleWeekdays = @(1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1)
$HourUsageScheduleWeekend = @(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
#standard variables
$ja = new-Object System.Management.Automation.Host.ChoiceDescription “&Yes”,”help”
$nee = new-Object System.Management.Automation.Host.ChoiceDescription “&No”,”help”

if($site_name -eq “”) {
$site_code = Read-Host “Enter your site code (for example: EU1)”
if($server_name -eq “”) {
$server_name = Read-Host “Enter the FQDN of your new distribution point (for example: dp01.ogd.local)”
if($driveletter_plibrary -eq “”) {
$driveletter_plibrary = Read-Host “Enter the driveletter for the primary content library (for example: E)”
if($driveletter_pshare -eq “”) {
$driveletter_pshare = Read-Host “Enter the driveletter for the primary content share (for example: E)”
if($add_statemigrationpoint -eq $true -And $state_migrationpoint_localpath -eq “”){
$state_migrationpoint_localpath = Read-Host “Enter the path your state migration point should use to store data (use quotes, for example: “C:\USMT”)”
if($distributionpointgroup -eq “”) {
$distributionpointgroup = Read-Host “Enter the name of the group you wish your distribution point to be a member of (for example OGD Production Site)”
if($add_schedule -eq $true){
if($block_size -eq 0){
$block_size = Read-Host(“Specify the maximum block size in KB for the Pulse Rate (min 1, max 256)”)
if($block_delay -eq 0){
$block_delay = Read-Host(“Specify the delay between blocks (min 1, max 30)”)
if([int]$block_delay -gt 30) {[int]$block_delay = 30}
if([int]$block_delay -lt 1) {[int]$block_delay = 1}
if([int]$block_size -gt 256) {[int]$block_size = 256}
if([int]$block_size -lt 1) {[int]$block_size = 1}

#bind to correct site
Set-Location $site_code”:”
Write-Host “”
Write-Host “”
Write-Host “We have enough information to proceed, the following will take place:”
Write-Host ” * A distribution point will be added to site $site_code”
Write-Host ” * The FQDN is $server_name”
Write-Host ” * A Content Library will be placed on drive $driveletter_plibrary”
Write-Host ” * A Content Share will be placed on drive $driveletter_pshare”
Write-Host ” * The DP will be added to the $distributionpointgroup group”
if($add_statemigrationpoint -eq $true){
Write-Host ” * A state migration point will be added”
Write-Host ” * State Migration Point Storage Path: $state_migrationpoint_localpath”
$folders = New-CMStorageFolder -StorageFolderName $state_migrationpoint_localpath -MaximumClientNumber 100 -MinimumFreeSpace 100 -SpaceUnit Megabyte
Write-Host ” * A state migration point will NOT be added”
if($add_schedule -eq $true){
Write-Host ” * Rate Limitation will be set to $block_size KB per $block_delay seconds according to schedule in config”
Write-Host ” * Rate Limitation will NOT be configured”

Write-Host “”
$options = [System.Management.Automation.Host.ChoiceDescription[]]($ja,$nee)
$prompt = $host.ui.PromptForChoice(“”,”Do you wish to proceed?”,$options,0)
Write-Host “”
if($prompt -eq 1) {
Write-Host “Cancelled…”

new-CMSiteSystemServer -ServerName $server_name -SiteCode $site_code

add-CMdistributionpoint -SiteSystemServerName $server_name -SiteCode $site_code -CertificateExpirationTimeUtc “Monday, January 2, 2017 1:00:00 AM” -MinimumFreeSpaceMB 5000 -InstallInternetServer -PrimaryContentLibraryLocation $driveletter_plibrary -PrimaryPackageShareLocation $driveletter_pshare -EnablePxeSupport -AllowRespondIncomingPxeRequest -EnableUnknownComputerSupport

add-CMDistributionPointToGroup -DistributionPointName $server_name -DistributionPointGroupName $distributionpointgroup
if($add_statemigrationpoint -eq $true){
add-cmstatemigrationpoint -EnableRestoreOnlyMode $false -sitesystemservername $server_name -sitecode $site_code -storagefolders $folders -TimeDeleteAfter 7 -TimeUnit Days -AllowFallBackSourceLocationForContent $false

if($add_schedule -eq $true){

$Percent = 100
$UsageAsBackup = @($true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true,$true)

$RateLimitingSchedule = @($Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent,$Percent)

$class_SMS_SCI_ADDRESS = [wmiclass]””
$class_SMS_SCI_ADDRESS.psbase.Path =”ROOT\SMS\Site_$($site_code):$($SMS_SCI_ADDRESS)”

$SMS_SCI_ADDRESS = $class_SMS_SCI_ADDRESS.CreateInstance()
# Set the UsageSchedule For Weekdays
$SMS_SiteControlDaySchedule = “SMS_SiteControlDaySchedule”
$SMS_SiteControlDaySchedule_class = [wmiclass]””
$SMS_SiteControlDaySchedule_class.psbase.Path = “ROOT\SMS\Site_$($site_code):$($SMS_SiteControlDaySchedule)”
$SMS_SiteControlDaySchedule = $SMS_SiteControlDaySchedule_class.createInstance()
$SMS_SiteControlDaySchedule.Backup = $UsageAsBackup
$SMS_SiteControlDaySchedule.HourUsage = $HourUsageScheduleWeekdays
$SMS_SiteControlDaySchedule.Update = $true

# Set the UsageSchedule For Weekend
$SMS_SiteControlDayScheduleWeekend = “SMS_SiteControlDaySchedule”
$SMS_SiteControlDayScheduleWeekend_class = [wmiclass]””
$SMS_SiteControlDayScheduleWeekend_class.psbase.Path = “ROOT\SMS\Site_$($site_code):$($SMS_SiteControlDayScheduleWeekend)”
$SMS_SiteControlDayScheduleWeekend = $SMS_SiteControlDayScheduleWeekend_class.createInstance()
$SMS_SiteControlDayScheduleWeekend.Backup = $UsageAsBackup
$SMS_SiteControlDayScheduleWeekend.HourUsage = $HourUsageScheduleWeekend
$SMS_SiteControlDayScheduleWeekend.Update = $true

$SMS_SCI_ADDRESS.UsageSchedule = @($SMS_SiteControlDayScheduleWeekend,$SMS_SiteControlDaySchedule,$SMS_SiteControlDaySchedule,$SMS_SiteControlDaySchedule,$SMS_SiteControlDaySchedule,$SMS_SiteControlDaySchedule,$SMS_SiteControlDayScheduleWeekend)

$SMS_SCI_ADDRESS.RateLimitingSchedule = $RateLimitingSchedule

$SMS_SCI_ADDRESS.AddressPriorityOrder = “0”
$SMS_SCI_ADDRESS.DesSiteCode = “$($server_name)”
$SMS_SCI_ADDRESS.DestinationType = “1”
$SMS_SCI_ADDRESS.SiteCode = “$($site_code)”
$SMS_SCI_ADDRESS.UnlimitedRateForAll = $false

# Set the embedded Properties
$embeddedpropertyList = $null
$embeddedproperty_class = [wmiclass]””
$embeddedproperty_class.psbase.Path = “ROOT\SMS\Site_$($site_code):SMS_EmbeddedPropertyList”
$embeddedpropertyList = $embeddedproperty_class.createInstance()
$embeddedpropertyList.PropertyListName = “Pulse Mode”
$embeddedpropertyList.Values = @(1,$block_size,$block_delay) #second value is size of data block in KB, third is delay between data blocks in seconds

$SMS_SCI_ADDRESS.PropLists += $embeddedpropertyList

$embeddedproperty = $null
$embeddedproperty_class = [wmiclass]””
$embeddedproperty_class.psbase.Path = “ROOT\SMS\Site_$($site_code):SMS_EmbeddedProperty”
$embeddedproperty = $embeddedproperty_class.createInstance()
$embeddedproperty.PropertyName = “Connection Point”
$embeddedproperty.Value = “0”
$embeddedproperty.Value1 = “$($server_name)”
$embeddedproperty.Value2 = “SMS_DP$”
$SMS_SCI_ADDRESS.Props += $embeddedproperty

$embeddedproperty = $null
$embeddedproperty_class = [wmiclass]””
$embeddedproperty_class.psbase.Path = “ROOT\SMS\Site_$($site_code):SMS_EmbeddedProperty”
$embeddedproperty = $embeddedproperty_class.createInstance()
$embeddedproperty.PropertyName = “LAN Login”
$embeddedproperty.Value = “0”
$embeddedproperty.Value1 = “”
$embeddedproperty.Value2 = “”
$SMS_SCI_ADDRESS.Props += $embeddedproperty

$SMS_SCI_ADDRESS.Put() | Out-Null
#In case your executionpolicy is restricted and you can’t modify it, paste these lines before calling the script
#Copyright Oisin Grehan
#START (remove #’s)
#function Disable-ExecutionPolicy {
#($ctx = $executioncontext.gettype().getfield(“_context”,”nonpublic,instance”).getvalue($executioncontext)).gettype().getfield(“_authorizationManager”,”nonpublic,instance”).setvalue($ctx, (new-object System.Management.Automation.AuthorizationManager “Microsoft.PowerShell”))

Leave a Reply

3 Comment threads
3 Thread replies
Most reacted comment
Hottest comment thread
3 Comment authors
JosDanielStephane Faubert Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

newest oldest most voted
Notify of

This script has been very useful as we’re improving our automation of processes and procedures. The issue that we have is that we have 4 different management servers and I cannot figure out how to take the $add_schedule piece to run from my machine to one of the four servers. I have at the beginning the script to create the required variables to define the MP, but it always runs locally and fails. I tried modifying all the Paths like below…
$SMS_SiteControlDaySchedule_class.psbase.Path = “\\$($MGMTPoint)\ROOT\SMS\Site_$($site_code):$($SMS_SiteControlDaySchedule)”
This didn’t seem to work or create an error either. Can you help?

Stephane Faubert
Stephane Faubert

Hello Jos,

Thanks for your reply! I didn’t have a chance to test out your code because while waiting for different replies here and there I went the good old fashion way: trial and error. Took a while, but I was able to achieve what I was looking for.

However, looking over your code it looks to be exactly what I did as well 🙂

Here’s to hoping it servers other people as well 🙂

Thanks once more!!!

Stephane Faubert
Stephane Faubert

Hi Jos,

Any chance you would be able to share a slightly modified version of this code that ONLY sets the priority for each day?

I am hoping to do something similar to what you did, except I want to have Monday to Friday, from 8 am to 8 pm “Allow High Priority Only” and the rest of the time, weekends included, All Priorities.

I don’t want to install anything else.

Any chance you could help me out?

Thanks! 🙂