Clean up finished installations

Go through a device collection folder, find all the Success or Already Present status devices, and remove them from the collection.

This creates a second powershell script so you can view the results before you execute the removals.

# ==[ Load modules
cd "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
Import-Module .\ConfigurationManager.psd1 -ErrorAction SilentlyContinue
if ((Get-PSDrive | Where-Object -Property provider -like -value '*cmsite') -eq $null) {
    Write-Verbose -Verbose 'ConfigurationManager.psd1 module not loaded / provider not available.'
    exit
}

cd fa0:

                    $Namespace = 'root\sms\site_FA0'
                   $SiteServer = 'SNAVPAPPSCCM001'
                   $ObjectType = 5000 # Device objects
$SoftwareDeploymentsFoldername = 'Software Deployments'
                            $S = ''   # output string

$ExclusionList = ('FA00513E')

$StartTime = $(get-date) # start a timer to measure how long it takes

# find the parent container nodeIDto make sure we look in the \_CLM folder, because the foldername is not unique
$ParentContainerNodeID = (`
    get-wmiobject -ComputerName $SiteServer `
        -Namespace $Namespace `
        -class SMS_ObjectContainernode `
        -filter "ObjectType = 5000 AND Name = '_CLM' AND ParentContainerNodeID = 0"`
    ).ContainerNodeID

# get the folder that contains all all the device collections we want to cleanup
$folder = get-wmiobject -ComputerName $SiteServer `
                        -Namespace $Namespace `
                        -class SMS_ObjectContainernode `
                        -filter "ObjectType = $ObjectType AND Name = '$SoftwareDeploymentsFoldername' and ParentContainerNodeID = $ParentContainerNodeID"

if ($folder -ne $null) {
    # get the list of device collections in this folder
    $CollectionList = get-wmiobject -ComputerName $siteServer `
                                    -Namespace $Namespace `
                                    -class SMS_ObjectContainerItem `
                                    -filter "ContainerNodeID = $($folder.ContainerNodeID)" | 
        Sort-Object -Property instanceKey 

    $CollectionCount = 0
    foreach ($ThisColl in $CollectionList) {
        $CollectionCount += 1
        
        $ThisObject = get-wmiobject -ComputerName $siteServer -Namespace $Namespace  -class SMS_Collection -filter "CollectionID = '$($ThisColl.InstanceKey)'"
        $CollectionName = $ThisObject.Name
        $CollectionID = $ThisObject.CollectionID
        Write-host "[$CollectionCount] $CollectionName ($CollectionID)"

        if (!($ExclusionList.contains($CollectionID))) { # if not excluded

            # Find the deployment - if more than 1 deployment, skip it.
            $ThisDeployment = (Get-CMApplicationDeployment -CollectionId $ThisColl.InstanceKey)
            if ($ThisDeployment.count -eq 1){
                # write-host $ThisDeployment.AssignmentName

                # get the various possible statuses.  We want 1000 (Success) or 1001 (Already installed)
                $DeploymentStatus = (
                    Get-CMApplicationDeploymentStatus -InputObject $ThisDeployment |
                    Where-Object -Property EnforcementState -like "100*"
                )

                ## # write out a summary of how many of each 
                ## $DeploymentStatus |                 
                ##     foreach {"Status: $($_.enforcementstate) - $( $_.Total) systems" } 

                # list all the machines 
                $DeploymentStatus |
                    foreach {
                        # get details 
                        Get-CMDeploymentStatusDetails -InputObject $_  | 
                        foreach {
                            $MachineName = $_.MachineName
                            $MachineID = $_.MachineID
                            Write-Host "Remove $MachineName from $CollectionName" -ForegroundColor Green
                            $S += "Remove-CMDeviceCollectionDirectMembershipRule -Whatif -CollectionName '$CollectionName' -ResourceId $MachineID`r`n"
                        }
                    }

            } # If count -eq 1         
        } # if not excluded
    } # foreach loop
} else {
    Write-Host "$SoftwareDeploymentsFoldername not found"
} # if folder -ne $null

$S

$elapsedTime = $(get-date) - $StartTime
$totalTime = "Elapsed time: " + "{0:HH:mm:ss}" -f ([datetime]$elapsedTime.Ticks) 
$totalTime


Leave a comment