RicardoPereira

SCCM - Add Device Collection with RuleQuery

Discussion created by RicardoPereira on Oct 31, 2018
We recently had a problem in the collection population with RuleDirect, which is that to 
install or reinstall a new operating system, the computer needs to be removed from SCCM.
The impact of this on the implementation of computers in collections with RuleDirect is
excluded from the SCCM and also from the collection and even after the installation of the
new operating system the computer did not return to collection anymore. To solve this issue, we started to implement the inclusion of new computers in the collection
based on RuleQuery.
Below is an excerpt of the code we use to perform this implementation.

 

param(
[Parameter(Mandatory=$true)][string]$SCCMUserName,
[Parameter(Mandatory=$true)][string]$SCCMServer,
[Parameter(Mandatory=$true)][string]$SCCMSiteCode,
[Parameter(Mandatory=$true)][string]$ComputerDevice,
[Parameter(Mandatory=$true)][string]$CollectionID

)


$SCCMServiceAccountName = Get-APSetting SCCMServiceAccountName
$SCCMServiceAccount = Get-ServiceAccount -Name $SCCMServiceAccountName -Scope 0
$SCCMServiceAccountPassword = $SCCMServiceAccount.Password | ConvertTo-SecureString -AsPlainText -Force
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SCCMUserName,$SCCMServiceAccountPassword

$ParamConnectSCCM = [ordered]@{
"NameSpace" = "Root\SMS\Site_$SCCMSiteCode"
"ComputerName" = $SCCMServer
"Credential" = $Credentials
"ErrorAction" = 'Stop'
}

### ComputerDevice Validation ###
try{
if($ComputerDevice.Contains('\')){
$Domain = $ComputerDevice.Split('\')[0]
$HostName = $ComputerDevice.Split('\')[1]
$ComputerObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$HostName' AND ResourceDomainORWorkgroup = '$Domain' AND Client = '1'" @ParamConnectSCCM)
}
else{
$ComputerObj = @(Get-WmiObject -Class SMS_R_SYSTEM -Filter "Name = '$ComputerDevice' AND Client = '1'" @ParamConnectSCCM)
}
if($ComputerObj.Count -gt 1){
Write-Error "Found more than one record with the name $ComputerDevice with attributes Client = 1"
}
if($ComputerObj.Count -eq 1){
Write-Host "The computer: $($ComputerObj.Name) was found with the following ID: $($ComputerObj.ResourceId)"
}
if($ComputerObj.Count -eq 0){
Write-Error "The computer: $($ComputerDevice) not found in SCCM"
}
}
catch{
Write-Error "Error while browsing the computer $ComputerDevice. Exception: $($_. Exception.Message)"
}

### CollectionID Validation ###
try{
$CollectionObj = @(Get-WmiObject -Class SMS_Collection -Filter "CollectionID = '$CollectionID' AND CollectionType = 2" @ParamConnectSCCM)
if($CollectionObj.Count -eq 1){
$CollectionObj = $CollectionObj[0]
Write-Host "The Collection: $($CollectionObj.CollectionID) was found in SCCM with the name: $($CollectionObj.Name)."
}
if($CollectionObj.Count -eq 0){
Write-Error "The Collection: $($CollectionID) not found in SCCM"
}
if($CollectionObj.Count -gt 1){
Write-Error "Found more than one record with ID: $($CollectionID)."
}
}
catch{
Write-Error "Error while browsing then collection $($CollectionID). Exception: $($_.Exception.Message)"
}

### Include, Create and Update Collection ###

$ArrayRules = @()
$ArrayComputer = @()

if($ComputerObj.Count -eq 1){

foreach($Collection in $CollectionObj){
$Collection.Get()
$CollectionRule = $Collection.CollectionRules
if($CollectionRule.Count -eq 0){
Write-Host "The collection $($CollectionObj.Name) does not have a RuleQuery created. The initial RuleQuery will be created."
$FirstQuery = 'select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.NetbiosName in ("0",'+'"'+$ComputerObj.Name+'"'+')'
try{
$FirstRule = (Get-WmiObject -List -Class SMS_CollectionRuleQuery @ParamConnectSCCM).CreateInstance()
$FirstRule.QueryExpression = $FirstQuery
$FirstRule.RuleName = $CollectionObj.Name
$Collection.Put() | Out-Null
if(($Collection.CollectionRules | Where-Object { ($_.RuleName -like "$($FirstRule.RuleName)") -and ($_.__CLASS -like "SMS_CollectionRuleQuery") } | Measure-Object).Count -eq 1){
Write-Host "QueryRule was successfully created. Name: '$($FirstRule.RuleName)' in collection '$($CollectionObj.Name)"
$InvokeUpdate = $Collection.RequestRefresh()
if($InvokeUpdate.ReturnValue -eq 0){
Write-Host "Installation | Added $($ComputerObj.Name) in collection $($CollectionObj.Name)."
}
else{
Write-Error "Failed to update collection $($CollectionObjInstall.Name)."
}

}
}
catch{
Write-Error "Failed to create RuleQuery instance. Exception: $($_.Exception.Message)"
}
}
if($CollectionRule.Count -ne 0){
Write-Host "The collection $($CollectionObj.Name) has one or more associated Rule. A single RuleQuery containing all members will be created."
foreach($Rule in $Collection.CollectionRules){
if($Rule.__CLASS -eq "SMS_CollectionRuleDirect"){
$ArrayRules += $Rule.RuleName
}
if($Rule.__CLASS -eq "SMS_CollectionRuleQuery"){
$Query = $Rule.QueryExpression
$List = $Query.Split('()')[1].Split(',').Split(' ').Split('"',[System.StringSplitOptions]::RemoveEmptyEntries).Split('"', [System.StringSplitOptions]::RemoveEmptyEntries)
$ArrayComputer += $List
}
}
$NewArray = @()
$NewArray = $ArrayRules + $ArrayComputer | select -Unique
$NewArrayQuery = @()

foreach($PC in $NewArray){
if($PC -notin 0){
$NovaArrayQuery += ',"'+$PC+'"'
}
}
$NewArrayQuery += ',"'+$ComputerObj.Name+'"'
$NewArrayQuery = $NewArrayQuery | select -Unique
$Replace = 'select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.NetbiosName in ("0"'+$NewArrayQuery+')'
Write-Host "New select associate ($Replace)"
try{
$NewRule = (Get-WmiObject -List -Class SMS_CollectionRuleQuery @ParamConnectSCCM).CreateInstance()
$NewRule.QueryExpression = $Replace
$NewRule.RuleName = $CollectionObj.Name
$Collection.Put() | Out-Null
if(($Collection.CollectionRules | Where-Object { ($_.RuleName -like "$($NewRule.RuleName)") -and ($_.__CLASS -like "SMS_CollectionRuleQuery") } | Measure-Object).Count -eq 1){
Write-Host = "QueryRule was successfully created. Name: '$($NewRule.RuleName)' in collection '$($CollectionObj.Name)."
$InvokeUpdate = $Collection.RequestRefresh()
if($InvokeUpdate.ReturnValue -eq 0){
Write-Host "The Collection $($CollectionObj.Name) has been updated with the new RuleQuery, containing the new computer: $($ComputerObj.Name)."
Write-Host "Installation | Added $($ComputerObj.Name) in collection $($CollectionObj.Name)."
}
else{
Write-Error "Failed to update collection $($CollectionObjInstall.Name)."
}
}
}
catch{
Write-Error "Failed to create RuleQuery instance. Exception: $($_.Exception.Message)"
}
}
}

}

Outcomes