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