Home
Microsoft
First published on TechNet on Apr 10, 2009

After you have created a collection, you need to be able to populate it with either direct membership rules or query rules.  That’s where the next function comes into play.  As with the previous examples, take the following script code and add it to your growing SCCM.PSM1 file:

--- snip ---

function Add-SCCMCollectionRule
{
[CmdletBinding()]
PARAM
(
[Parameter(ValueFromPipelineByPropertyName=$true)] $collectionID,
[Parameter(ValueFromPipeline=$true)] [String[]] $name,
[Parameter()] $queryExpression,
[Parameter()] $queryRuleName
)
Process
{
# Get the specified collection (to make sure we have the lazy properties)
$coll = [wmi]"\\$sccmServer\$($sccmNamespace):SMS_Collection.CollectionID='$collectionID'"

# Build the new rule
if ($queryExpression -ne $null)
{
# Create a query rule
$ruleClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_CollectionRuleQuery"
$newRule = $ruleClass.CreateInstance()
$newRule.RuleName = $queryRuleName
$newRule.QueryExpression = $queryExpression

$null = $coll.AddMembershipRule($newRule)
}
else
{
$ruleClass = [wmiclass]"\\$sccmServer\$($sccmNamespace):SMS_CollectionRuleDirect"

# Find each computer
foreach ($n in $name)
{
foreach ($computer in get-SCCMComputer -filter "Name = '$n'")
{
# See if the computer is already a member
$found = $false
if ($coll.CollectionRules -ne $null)
{
foreach ($member in $coll.CollectionRules)
{
if ($member.ResourceID -eq $computer.ResourceID)
{
$found = $true
}
}
}
if (-not $found)
{
Write-Verbose "Adding new rule for computer $n"
$newRule = $ruleClass.CreateInstance()
$newRule.RuleName = $n
$newRule.ResourceClassName = "SMS_R_System"
$newRule.ResourceID = $computer.ResourceID

$null = $coll.AddMembershipRule($newRule)
}
else
{
Write-Verbose "Computer $n is already in the collection"
}
}
}
}
}
}

--- snip ---

So now you can add a static collection membership rule or a query rule:

Connect-SCCMServer

Add-SCCMCollectionRule -collectionID CEN00001 -name MYSERVER

Add-SCCMCollectionRule -collectionID CEN00001 -queryRuleName "My Rule" -queryExpression "select * from SMS_R_System"

But notice that the function above can actually accept some inputs from the PowerShell pipeline.  That means you can get more creative.  For example, assume you have a file that has the list of machines you want to add, something like this Computers.txt file that has one computer name per line:

COMPUTER1

COMPUTER2

COMPUTER3

With that, you can do something like this:

Get-Content C:\Computers.txt | add-SCCMCollectionRule -collectionID CEN00001

It will add three new rules to the collection.  Or, if you want to create a collection and add a member at the same time, you can pipe the collection into the collection rule function:

New-SCCMCollection -name "My Collection" | Add-SCCMCollectionRule -name MYSERVER

A few comments on the logic above:

  • The above function can’t take a list of query rules from the pipeline, although it could be modified to do that – it could then take it’s input from the pipeline as well, maybe from the import-CSV cmdlet.
  • I tried to get PowerShell to call the AddMembershipRules function (to more efficiently add batches of rules) but I’ve been unable to get this to work.  (PowerShell wins that battle – for now.)
  • I really should be defining parameter sets that show which combinations of parameters are valid together (e.g. you shouldn’t specify -name at the same time as -queryExpression) and which should be specified together (e.g. -queryRuleName and -queryExpression should both be specified).
  • I should provide help text so you can use “get-help” to get the details.

Those are all exercises for some other time :-)