I’m going to show you a new approach to getting deployment status out of SCCM.

Most of our readers are familiar with using SCCM Reports, or the SCCM console, to get deployment status when asked.  Usually, when asked, I turn to SQL.  However, I was looking at all the cmdlets that come with SCCM when I realized: There are no cmdlets dedicated to simple reporting.

As such, I took it upon myself to create a simple cmdlet that returns both summary and details of the status of an Application Deployment. I’ll include the code at the bottom of this post, but first, I’ll show you how to use it.

The name of the script is CMReporting.ps1.  For now, all the required functions are within this script.

Using the Script to Get Deployment Status

To use this script, you first need to load the functions into memory by running the script.

This script must be run from the SCCM Site Server.

Here is one example on how to use it:

Get-CMAppDeploymentReport -ChooseFromGrid -DetailType Both -OutputType Text

You are first presented with a gridview list of all current app deployments.  Highlight one and click “OK”.



After about 30 seconds, you’ll see a display like the following in PowerShell:



As promised, here is the code:


Function Get-WindowsErrorMessage {


    param (
        $ErrorCode ,
        $ErrorSource = "Windows",

    #This error code was generated from the Windows Exception Library
    If ($ErrorSource -eq "Windows") {
        $ErrorMessage = [ComponentModel.Win32Exception]$ErrorCode

    #Write Output of Function
    If ($SimpleOutput) {
        Write-Output $ErrorMessage
    Else {
        Write-Output "$ErrorSource Error $($ErrorCode): $($ErrorMessage.Message)"


Function Get-CMAppDeploymentReport {


    #Select Deployment to Report on
    if($ChooseFromGrid) {

        $DeploymentList = Get-WMIObject -Namespace root\sms\site_mp1 -class SMS_DeploymentSummary -Filter "FeatureType = 1"

        $SelectedDeployment = $DeploymentList | Select-Object AssignmentID, CollectionName, SoftwareName, @{Name="DeploymentTime";Expression={$([Management.ManagementDateTimeConverter]::toDateTime($_.DeploymentTime))}},@{Name="DeploymentIntent";Expression={If ($_.DeploymentIntent -eq 1){"Required"}elseif($_.DeploymentIntent -eq 2){"Available"}else{"Unknown"}}},@{Name="EnforcementDeadline";Expression={$([Management.ManagementDateTimeConverter]::toDateTime($_.EnforcementDeadline))}} | Out-GridView -OutputMode Single -Title "Select a Deployment to Report on"

        $AssignmentID = $SelectedDeployment.AssignmentID


    #Get Summary Data
    $Summary = Get-WMIObject -Namespace root\sms\site_mp1 -class SMS_DeploymentSummary -Filter "AssignmentID = $AssignmentID and FeatureType = 1"

    $CollectionInfo = Get-WMIObject -Namespace root\sms\site_mp1 -Class SMS_Collection -Filter "CollectionID = ""$($Summary.CollectionID)"""

    If ($CollectionInfo.CollectionType -eq 2) {$CollectionType = "User"}elseif($CollectionInfo.CollectionType -eq 1){$CollectionType = "Device"}else{$CollectionType = "Other"}

    $SummaryTable = $Summary |Select-Object AssignmentID, CollectionID, CollectionName, SoftwareName, @{Name="DeploymentTime";Expression={$([Management.ManagementDateTimeConverter]::toDateTime($_.DeploymentTime))}},@{Name="DeploymentIntent";Expression={If ($_.DeploymentIntent -eq 1){"Required"}elseif($_.DeploymentIntent -eq 2){"Available"}else{"Unknown"}}},@{Name="EnforcementDeadline";Expression={$([Management.ManagementDateTimeConverter]::toDateTime($_.EnforcementDeadline))}}, NumberSuccess, NumberInProgress, NumberErrors, NumberUnknown, NumberTotal, PackageID

    $SummaryTitle = "Summary of Deployment for $($Summary.SoftwareName) to $($CollectionInfo.MemberCount) $($CollectionType)(s)"

    $DetailTitle = "Detail for Deployment of $($Summary.SoftwareName) to $($CollectionInfo.MemberCount) $($CollectionType)(s)"

    $OutputReport = New-Object -TypeName PSObject

    If ($DetailLevel -eq "Summary" -or $DetailLevel -eq "Both") {

        $OutputReport | Add-Member -MemberType NoteProperty -Name "SummaryTitle" -Value $SummaryTitle
        $OutputReport | Add-Member -MemberType NoteProperty -Name "SummaryResults" -Value $SummaryTable


    If ($DetailLevel -eq "Detail" -or $DetailLevel -eq "Both") {

        $States = Get-WMIObject -Namespace root\sms\site_mp1 -Class "SMS_StateInformation"
        #Get Detail Data

        $Detail = Get-WMIObject -Namespace root\sms\site_mp1 -class SMS_AppDeploymentAssetDetails -Filter "AssignmentID = $AssignmentID"

        $Devices = @()

        Foreach ($Target in $Detail) {

            If ($Target.AppStatusType -eq 5) {
            $ErrorCode = $(Get-WMIObject -Namespace root\sms\site_mp1 -class SMS_AppDeploymentErrorAssetDetails -Filter "MachineID = $($Target.MachineID) and AssignmentID = $AssignmentID").ErrorCode
            $ErrorMessage = Get-WindowsErrorMessage -ErrorCode $ErrorCode
            Else {
            $ErrorCode = ""
            $ErrorMessage = ""

            $CIComplianceInfo = Get-WmiObject -Namespace root\SMS\site_mp1 -Class SMS_CI_ComplianceHistory -Filter "ResourceID = $($Target.MachineID) and CI_ID = $($Target.AppCI)"

            $Device = New-Object -TypeName PSObject
            #$Device | Add-Member -MemberType NoteProperty -Name "ComplianceState" -Value "$(If ($Target.ComplianceState -eq 1){"Compliant"}elseif($Target.ComplianceState -eq 2){"Non-Compliant"}else{"Unknown"})"
            $Device | Add-Member -MemberType NoteProperty -Name "Name" -Value "$($Target.MachineName)"
            $Device | Add-Member -MemberType NoteProperty -Name "State" -Value "$(if ($Target.AppStatusType -eq 1) {"Success"} elseif ($Target.AppStatusType -eq 2) {"In Progress"} elseif ($Target.AppStatusType -eq 3){"Requirements Not Met"} elseif ($Target.AppStatusType -eq 4) {"Unknown"} elseif($target.AppStatusType -eq 5) {"Error"})"
            #If($Device.State -eq "
            $Device | Add-Member -MemberType NoteProperty -Name "ErrorCode" -Value "$ErrorCode"
            $Device | Add-Member -MemberType NoteProperty -Name "ErrorMessage" -Value "$ErrorMessage"
            Try {

            $CIComplianceInfo = $CIComplianceInfo | Sort-Object -Property ComplianceStartDate -Descending | Select * -First 1
            $Device | Add-Member -MemberType NoteProperty -Name "LastComplianceStateChange" -Value "$([Management.ManagementDateTimeConverter]::toDateTime($($CIComplianceInfo.ComplianceStartDate)))"
            Catch {
              $Device | Add-Member -MemberType NoteProperty -Name "LastComplianceStateChange" -Value ""

            $Devices += $Device


        $OutputReport | Add-Member -MemberType NoteProperty -Name "DetailTitle" -Value $DetailTitle

         $OutputReport | Add-Member -MemberType NoteProperty -Name "DetailResults" -Value $Devices

     If ($OutputType -eq "Object") {
          Write-Output $OutputReport
    elseif ($OutputType -eq "Text") {
        If ($DetailLevel -eq "Summary" -or $DetailLevel -eq "Both"){
            Write-Host ""
            Write-Host ""
            $($OutputReport.SummaryResults | ft -AutoSize)


        If ($DetailLevel -eq "Detail" -or $DetailLevel -eq "Both"){

            Write-Host ""
            Write-Host ""
            $($OutputReport.DetailResults | Select Name, State, ErrorCode, ErrorMessage, LastComplianceStateChange -Unique | Sort-Object -Property Name | ft -AutoSize)





About the Author: steve bowman

Three Minutes For A More Secure & Efficient Infrastructure

Short and to the point, Steve’s Email Blasts give you endpoint management tips, tricks, and news in three minutes or less email read-time, guaranteed.

Model says no to spam. Privacy Policy

Model Technology Solutions

Model Technology Solutions is a small but mighty band of infrastructure experts. We’ve helped companies in diverse industries to modernize and automate their infrastructures through effectively managing their Microsoft endpoint suite.

With us on your team, you’ll watch your security and compliance go up and your IT team’s costs (and headaches) go down. You’ll relax in knowing that your endpoints will be secure and online when your users need them most. And you’ll finally get back to your most-important tasks.

Model Technology Solutions
12125 Woodcrest Executive Drive, Ste. 204 Creve Coeur, MO 63141

Phone: (314) 254-4138
General Inquiries: model@model-technology.com
Sales and Quotes: sales@model-technology.com