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.

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 *

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

%d bloggers like this: