I developed some automation for a customer to help them manage the lifecycle of collections used for assignment of DCM baselines as they are revised.  Part of this required the ability to convert a collection from query-based membership to direct membership rules and vice versa.  I realize this is a very niche piece of automation, but perhaps someone else can gain some benefit from these functions.

I used Michael Niehaus’ Windows PowerShell module for Configuration Manager to provide supporting functions and even derived several of the code blocks from his very handy functions.  SCCM.psm1 is not technically required for these functions, but I assume it was used to create the connection to the site so that variables such as $sccmServer and $sccmNamespace are available.

There are three functions:

  • Add-SCCMCollectionDirectRule: this is a helper function used by both of the following.  It takes two parameters: a collection object and an array of collection members.  (It is a simplification of Michael’s related function.)
  • Convert-SCCMCollectionToDirect: as the name suggests this will take any collection, capture the current membership, remove the rule and then add the members as direct membership rules.  It assumes there is only one query rule and does not refresh the collection membership.
  • Convert-SCCMCollectionToQuery: the converse of the above; it removes all direct membership rules and then adds the given query rule.  It is adapted from Michael’s code with fewer parameters (which could easily be added back for increased functionality).


Function Add-SCCMCollectionDirectRule {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection,
        # Array of SMS_CollectionMembers from MemberClassName WMI Class
        [Parameter()] $Members

    # (derived from Add-SCCMCollectionRule in SCCM.psm1 by Michael Niehaus)
    $ruleClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_CollectionRuleDirect"
    ForEach ( $member in $Members ) {
        $newRule = $ruleClass.CreateInstance()
        $newRule.RuleName = $member.Name
        $newRule.ResourceClassName = "SMS_R_System"
        $newRule.ResourceID = $member.ResourceID

        $Collection.AddMembershipRule($newRule) | Out-Null
    }  # end foreach

}  # end Add-SCCMCollectionDirectRule function

Function Convert-SCCMCollectionToDirect {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection

    # Refresh to make sure we have all of the lazy properties

    # Change the schedule from periodic (2) to manual (1)
    $Collection.RefreshType = 1
    $Collection.Put() | Out-Null

    # Get the collection members
    $collMembers = Get-WmiObject -Class $Collection.MemberClassName -Namespace $sccmNamespace -ComputerName $sccmServer

    # Get the existing query rule, assuming there is only one
    $rule = $Collection.CollectionRules[0]

    # Delete the query rule
    $Collection.DeleteMembershipRule($rule) | Out-Null

    # Add members back as direct membership rules
    Add-SCCMCollectionDirectRule -Collection $Collection -Members $collMembers

}  # end Convert-SCCMCollectionToDirect function

Function Convert-SCCMCollectionToQuery {

    Param (
        # SMS_Collection object, such as returned from Get-SCCMCollection function of SCCM.psm1
        [Parameter()] $Collection,
        [Parameter()] $QueryName,
        [Parameter()] $Query,
        [Parameter()] [ValidateRange(0, 31)] [int] $RefreshDays

    # Get all lazy properties

    #Set schedule
    $intervalClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_ST_RecurInterval"
    $interval = $intervalClass.CreateInstance()
    $interval.DaySpan = $refreshDays
    $Collection.RefreshSchedule = $interval
    $Collection.RefreshType = 2    # periodic (2) vs manual (1)
    $Collection.Put() | Out-Null

    # Delete all direct membership rules
    ForEach ( $rule in $Collection.CollectionRules ) {
        $Collection.DeleteMembershipRule($rule) | Out-Null

    # Add query
    Add-SCCMCollectionRule -collectionID $Collection.CollectionID -queryRuleNameb $queryName -queryExpression $query

    # refresh the collection
    $Collection.RequestRefresh() | Out-Null

}  # end Convert-SCCMCollectionToQuery function


Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.