How to locate SCCM Collection Object based on the Collection ID

Often, I found it’s hard to locate the Collection object in the SCCM console if you only know the Collection ID. Couple of weeks ago I ran into a situation where I need to modify the settings of a bunch of collection objects and all I knew was the Collection ID.

I wrote a script called Get-CollectionPath that identifies all possible paths to a particular collection (as a collection can be linked to multiple places).

The Syntax is: .\Get-CollectionPath <SCCM Central Site Server Name> <Collection ID>

image

Download the script here.

[sourcecode language=”powershell”]
param([string]$CentralSiteServer,[string[]]$CollectionID)
Function Get-CollectionName ($CollectionID)
{
$CollectionName = (Get-WmiObject -ComputerName $CentralSiteProvider -Namespace root\sms\site_$CentralSiteCode -Query "Select * from SMS_Collection where CollectionID = ‘$CollectionID’").name
Return $CollectionName
}
Function Get-ParentCollectionID ($subCollectionID)
{
$arrParentCollectionID =@()
$objCollectToSubCollect = Get-WmiObject -ComputerName $CentralSiteProvider -Namespace root\sms\site_$CentralSiteCode -Query "Select * from SMS_CollectToSubCollect where SubCollectionID = ‘$subCollectionID’"
if (($objCollectToSubCollect.GetType()).IsArray -eq $true)
{
Foreach ($item in $objCollectToSubCollect)
{
$arrParentCollectionID += $item.ParentCollectionID
}
} else {
$arrParentCollectionID += $objCollectToSubCollect.ParentCollectionID
}
Return $arrParentCollectionID
}

Function Get-CollectionPathObject ($strBaseCollectionPath, $CollectionID)
{
$CollectionName = Get-CollectionName $CollectionID
if ($strBaseCollectionPath -eq $null) {$strBaseCollectionPath = "$CollectionName($CollectionID)"}
$arrParentID = Get-ParentCollectionID $CollectionID
$arrObjPath = @()
Foreach ($CollectionID in $arrParentID)
{
$ParentCollectionName = Get-CollectionName $CollectionID
$strCollectionPath = "$ParentCollectionName($CollectionID)\"+$strBaseCollectionPath
$objCollectionPath = New-Object psobject
Add-Member -InputObject $objCollectionPath -membertype noteproperty -name CollectionPath -value $strCollectionPath
Add-Member -InputObject $objCollectionPath -MemberType NoteProperty -Name ParentCollectionID -Value $CollectionID
$arrObjPath += $objCollectionPath
}
Return $arrObjPath
}

$objSite = Get-WmiObject -ComputerName $CentralSiteServer -Namespace root\sms -query "Select * from SMS_ProviderLocation WHERE ProviderForLocalSite = True"
$CentralSiteCode= $objSite.SiteCode
$CentralSiteProvider = $objSite.Machine

$arrObjCollectionPath = new-object System.Collections.ArrayList
$bFinished = $false
$arrPath = Get-CollectionPathObject $strCollectionPath $CollectionID

Foreach ($item in $arrPath) {$arrObjCollectionPath.Add($item) | Out-Null}
Remove-Variable arrPath
Do{
$arrObjTempNew = @()
$arrObjTempOld = @()
Foreach ($item in $arrObjCollectionPath)
{
$objCollectionPath = Get-CollectionPathObject $item.CollectionPath $item.ParentCollectionID
Foreach ($objPath in $objCollectionPath) {$arrObjTempNew += $objPath}
$arrObjTempNew += $objCollectionPath
$arrObjTempOld += $item
}
Foreach ($OldItem in $arrObjTempOld) {$arrObjCollectionPath.Remove($OldItem)}
Foreach ($NewItem in $arrObjTempNew) {If (!($arrObjCollectionPath.Contains($NewItem))) {$arrObjCollectionPath.Add($NewItem) | Out-Null}}
Remove-Variable arrObjTempOld
Remove-Variable arrObjTempNew

$AllReachedTop = $true
Foreach ($item in $arrObjCollectionPath)
{
if ($($item.ParentCollectionID) -ne "COLLROOT") {$AllReachedTop = $false}
}
IF ($AllReachedTop -eq $true) {$bFinished = $true}
} While ($bFinished -ne $true)
$arrOutput = @()
Foreach ($item in $arrObjCollectionPath) {$arrOutput += $item.CollectionPath}
$arrOutput | fl *
[/sourcecode]

3 comments

  1. Thank you for sharing awesome scripts on your site Tao Yang!

    I am having a similar issue that is related to this page topic but not exactly the same.

    I am able to get the collection ID but I am not able to find out which member a certain collection belongs to. For example, I want to be able to get a giant list of collections, find out what member they belong to, and be able to use -Filter and/OR -notlike, -like, and find out which servers are belonging to two of the same members. Please correct me if my technical terminology is inaccurate – I have just started learning PowerShell about 1 month ago.

    This is the script section that I want to run:

    $SMSMemebers = Get-WmiObject -ComputerName $SiteServer -Credential $MyCredential -Namespace “ROOT\SMS\site_$SiteCode” `
    -Query “SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID=’$($BaseCollection.CollectionID)’ order by name” | select Name

    Write-Output “The members of ALL windows servers are”
    write-output $SMSMemebers | Format-Table -AutoSize

    I am also getting confused with the terminology of a “collection” “members” “servers” which ones can be a part of which, can 1 of the term include/exclude the other, such as can a server be a member of one of the collection? etc…

    Thank you for posting this, I have used some of your other scripts and they are super helpful.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: