MSEndpointMgr

Automatically distribute Applications to a Distribution Point Group with PowerShell

In an earlier post, I wrote about how you can leverage PowerShell to distribute application and packages to a Distribution Point Group. The script that I’m using in that post may work, but the code is not nearly of any kind of best practice, or to be frank, good looking. At one of my recent projects that I’ve been involved with, we’ve migrated a log of packages to the application model. So I had to create a script that the customer could leverage when they were gonna distribute all the new applications.
Since the customer had created some applications themselves, the script would had to take into account so that it would only distribute applications created within a certain time frame. It was also necessary to be able to specify which Site server to run the script against, as well for what Distribution Point Group should be targeted.

Script

<#
.SYNOPSIS
    Distributes all Applications created within a certain time frame to a Distribution Point Group
.DESCRIPTION
    Distributes all Applications created within a certain time frame to a Distribution Point Group
.PARAMETER SiteServer
    Primary Site server name
.PARAMETER DPGName
    Specify a Distribution Point Group name
.PARAMETER CreatedDaysAgo
    Specify the amount of days ago an Application was created. The script will only enumerate Applications created within the specified time frame.
.EXAMPLE
    Start to distribute all Applications created within the last day to a Distribution Point Group called 'All DPs' on a Site server called 'CM01':
    .\Start-ApplicationDistribution.ps1 -SiteServer "CM01" -DPGName "All DPs"
.EXAMPLE
    Start to distribute all Applications created within the last 3 days to a Distribution Point Group called 'All DPs' on a Site server called 'CM01':
    .\Start-ApplicationDistribution.ps1 -SiteServer "CM01" -DPGName "All DPs" -CreatedDaysAgo 3
.NOTES
    Script name: Start-ApplicationDistribution.ps1
    Author:      Nickolaj Andersen
    Contact:     @NickolajA
    DateCreated: 2014-09-22
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
    

[parameter(Mandatory=$true, HelpMessage=”Specify the Primary Site server”)]

[ValidateScript({Test-Connection -ComputerName $_ -Count 2})] [string]$SiteServer = “$($env:COMPUTERNAME)”,

[parameter(Mandatory=$true, HelpMessage=”Specify the name of a Distribution Point Group”)]

[string]$DPGName,

[parameter(Mandatory=$false, HelpMessage=”Specify the name of a Distribution Point Group”)]

[int]$CreatedDaysAgo = 1 ) Begin { # Determine SiteCode from WMI try { Write-Verbose “Determining SiteCode for Site Server: ‘$($SiteServer)'” $SiteCodeObjects = Get-WmiObject -Namespace “root\SMS” -Class SMS_ProviderLocation -ComputerName $SiteServer -ErrorAction Stop foreach ($SiteCodeObject in $SiteCodeObjects) { if ($SiteCodeObject.ProviderForLocalSite -eq $true) { $SiteCode = $SiteCodeObject.SiteCode Write-Debug “SiteCode: $($SiteCode)” } } } catch [Exception] { Throw “Unable to determine SiteCode” } # Load the Configuration Manager 2012 PowerShell module try { Write-Verbose “Importing Configuration Manager module” Write-Debug ((($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) + “\ConfigurationManager.psd1”) Import-Module ((($env:SMS_ADMIN_UI_PATH).Substring(0,$env:SMS_ADMIN_UI_PATH.Length-5)) + “\ConfigurationManager.psd1”) -Force -ErrorAction Stop if ((Get-PSDrive $SiteCode -ErrorAction SilentlyContinue | Measure-Object).Count -ne 1) { New-PSDrive -Name $SiteCode -PSProvider “AdminUI.PS.Provider\CMSite” -Root $SiteServer -ErrorAction Stop } # Set the location to the Configuration Manager drive Set-Location ($SiteCode + “:”) } catch [Exception] { Throw $_.Exception.Message } } Process { # Validate specified Distribution Point Group try { $DPG = Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class SMS_DistributionPointGroup -ComputerName $SiteServer -Filter “Name = ‘$($DPGName)'” if (($DPG | Measure-Object).Count -eq 1) { Write-Verbose “Found Distribution Point Group: $($DPG.Name)” } elseif (($DPG | Measure-Object).Count -gt 1) { Throw “Query for DPGs returned more than 1 object” } else { Throw “Unable to determine Distribution Point Group name from specified string for parameter ‘DPGName'” } } catch [Exception] { Throw $_.Exception.Message } # Start Application distribution try { Write-Verbose “Enumerating applicable Applications” $Applications = Get-CMApplication | Select-Object LocalizedDisplayName, PackageID, DateCreated | Where-Object { $_.DateCreated -ge (Get-Date).AddDays(-$CreatedDaysAgo) } foreach ($Application in $Applications) { if (-not(Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class SMS_DPGroupDistributionStatusDetails -ComputerName $SiteServer -Filter “PackageID = ‘$($Application.PackageID)'” -ErrorAction SilentlyContinue)) { if ($PSCmdlet.ShouldProcess(“$($DPG.Name)”, “Distribute Application: $($Application.LocalizedDisplayName)”)) { $DPG.AddPackages($Application.PackageID) | Out-Null } } } Set-Location C: } catch [Exception] { Throw $_.Exception.Message } }

How to use the script

Save the script above as Start-ApplicationDistribution.ps1 to a folder somewhere, e.g. C:\Scripts.
Let’s say that we have a scenario where we’ve created 100 new applications and we need to distribute them to a Distribution Point Group called Global. In addition, there’s already a bunch of applications that was created earlier in time. Since the script accepts a parameter called CreatedDaysAgo, we can specify a number that correlates to how many days ago the application that we’re targeting was created. As we know that we’ve created all of our 100 applications within the last 2 days, we can then specify the parameter CreatedDaysAgo as 2. Here’s how you’d do that:
1. Open an elevated PowerShell console and browse to where you have the script.
2. Run the following command:

.\Start-ApplicationDistribution.ps1 -SiteServer "CAS01" -DPGName "Global" -CreatedDaysAgo 2

As the script accepts advanced PowerShell functions, you can also specify the -WhatIf parameter as well for the -Confirm, -Debug or -Verbose.
111_1
I hope this script will be useful for you!

Nickolaj Andersen

Chief Technical Architect and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences such as Microsoft Ignite, NIC Conference and IT/Dev Connections including nordic user groups.

Add comment

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.