Add task sequence dependencies to DP group

, , , , , ,

We’re working on adding new distribution point that are used exclusively for imaging.  This motivated me to create a script to make sure all dependent packages are assigned to the proper distribution point group.  (You are using distribution point groups right?)

Change the site code in the script and it will prompt you for the task sequence and then prompt for the distribution point group.  After that, magic!  🙂

I wasn’t planning on posting this one yet as it could use a lot of polish but I’m sure it’ll evolve as time goes on and I’ll do my best to keep this updated.

On to the code…

 

 

$siteCode = "CM1"

Import-Module ConfigurationManager
Push-Location
Set-Location "$($siteCode):"

$site = (Get-CMSite -SiteCode $siteCode)
$sequences = Get-CMTaskSequence | Select-Object -Property Name | Out-GridView -Title "Select task sequences for DG" -PassThru
$dg = Get-CMDistributionPointGroup | Out-GridView -Title "Select a distribution point group." -PassThru

if($ConfirmPreference -eq 'Low') {$conf = @{Confirm = $true}}

foreach ($tsname in $sequences)
{
    $ts = Get-CMTaskSequence -Name $tsname.Name
    Write-Host "References $($ts.References.Count)"
    foreach ($ref in $ts.References)
    {
        $pkgContentServer = $null
        $pkgId = $null

        if ($ref.Type -eq 0)
        {
            $pkgContentServer = Get-WmiObject -ComputerName $site.ServerName -Namespace "rootSMSsite_$($site.SiteCode)" -Class SMS_PackageContentServerInfo -Filter "PackageID = '$($ref.Package)' AND ContentServerID = '$($dg.GroupID)'"
            $pkgId = $ref.Package
        }
        elseif ($ref.Type -eq 1)
        {
            $app = Get-CMApplication -ModelName $ref.Package
            $pkgContentServer = Get-WmiObject -ComputerName $site.ServerName -Namespace "rootSMSsite_$($site.SiteCode)" -Class SMS_PackageContentServerInfo -Filter "PackageID = '$($app.PackageID)' AND ContentServerID = '$($dg.GroupID)'"
            $pkgId = $app.PackageID
        }

        if ($pkgContentServer -eq $null)
        {
            Write-Host "Adding distribution point group $($dg.Name) to package $($ref.Package)."
            if ($PSCmdlet.ShouldProcess("$($ref.Package)", "Distribute package"))
            {
                if ($ref.Type -eq 0)
                {
                    $baseObject = Get-WmiObject -ComputerName $site.ServerName -Namespace "rootSMSsite_$($site.SiteCode)" -Class SMS_PackageBaseClass -Filter "PackageID = '$pkgId'"
                    Start-CMContentDistribution -InputObject ($baseObject | ConvertTo-CMIResultObject) -DistributionPointGroupName $dg.Name #-WhatIf:([bool]$WhatIfPreference.IsPresent) #@conf
                }
                elseif ($ref.Type -eq 1)
                {
                    Start-CMContentDistribution -ApplicationId $app.CI_ID -DistributionPointGroupName $dg.Name
                }
            }
        }
    }

    $bootImage = Get-CMBootImage -Id $ts.BootImageID
    $pkgContentServer = Get-WmiObject -ComputerName $site.ServerName -Namespace "rootSMSsite_$($site.SiteCode)" -Class SMS_PackageContentServerInfo -Filter "PackageID = '$($bootImage.PackageID)' AND ContentServerID = '$($dg.GroupID)'"
    if ($pkgContentServer -eq $null)
    {
        Write-Host "Adding distribution point group $($dg.Name) to package $($bootImage.PackageID)."
        if ($PSCmdlet.ShouldProcess("$($bootImage.PackageID)", "Distribute package"))
        {
            $baseObject = Get-WmiObject -ComputerName $site.ServerName -Namespace "rootSMSsite_$($site.SiteCode)" -Class SMS_PackageBaseClass -Filter "PackageID = '$($bootImage.PackageID)'"
            Start-CMContentDistribution -InputObject ($baseObject | ConvertTo-CMIResultObject) -DistributionPointGroupName $dg.Name
        }
    }
}
Pop-Location


ALSO CHECK : Post OSD Scheduled Task

Quick and Dirty SCCM Application Deployment Reporting

, , , ,

For this blog, I’m going to go over a very basic script I wrote to quickly get application deployment statuses without having to use the Configuration Manager GUI console. I find the ReportingDeployments tab very slow to respond, and you still have to dig into each individual app if you want details.  What this function does is allow you to specify what you think is the name of the application and it will find anything like it, allow you to select the one you want, and then it will run a deployment summarization and output the results.

Examples:

Application Deployment
Function called with the correct name of the package

In this example, “Tanium Client” is the actual name of a software package, so it doesn’t need to pop up a prompt asking us which one we actually wanted.

Application Deployment
Function called with a keyword instead of the full package name
Application Deployment
After package was selected from the pop up
In the above two images, I didn’t remember the full name of my Tripwire deployments, so I just typed “Tripwire” and let it look for it for me.
The Code:
 
This is a fairly simple piece of code, but I wrote it to run quickly.  It first checks to see if the name you gave it when running already matches a software package. If not, it runs a WMI query (much faster than using Get-CMApplication with a where-object piped on) to look for anything like what you entered. It puts all results into an array which then selects the LocalizedDisplayName and filters out duplicates. Those unique values are then handed over to Out-GridView, which thanks to the -passthru flag assigns the selected result to our original $SoftwareName variable.  You’ll also see that I have to specify that I want the “.localizeddisplayname” NoteProperty. If you don’t do this, you’ll see the selected software name as “@LocalizedDisplayName={‘Whatever your name was’}”
After that selection process, everything proceeds as normal. It gets the CMDeployment object for that application and runs the Invoke-CMDeploymentSummarization cmdlet which refreshes the deployment status, gets you current numbers, etc.  After that, I have it get the deployment again and select what I found to be the relevant values for a list formatted report.  Because SummarizationTime is done in UTC, I have it convert to client local time for ease of reporting, and I also go ahead and do a quick math expression for the percent success, which is done with the Round function so we don’t get a dozen decimal places of needless precision.   The Query Time value was mostly tacked on at the end so the people I was getting this information for could see that the data was current.
Hopefully this is useful for someone out there. Thanks for reading!