SCCM and Powershell! adding nodes to a collection and trigger evaluation

Powershell is probably one of the most important tool you have if you want to make your work easier and find zen in life!

I could talk about powershell for hours on hours but for this post i just wanna mention one way i use powershell to populate device collections and trigger evaluation on the client in one go. This is helpful in situation where i have specific clients that needs to get an deployment straight away but i don’t want to wait for the next evaluation cycle. Sometimes i even do a schedule task for it if i have a set time i need to have it executed.

You could also turn this in to a much better function overall but for now this is a proof of concept on what you could do and keep on improving upon if you feel like it.

 

What do we want to achive?

We want to add the node called SQL1

1

In to the awesome device collection, awesome collection!

2

when that’s done we want the client to trigger the defined evaluation we need,

3

 

Here’s the powershell code that will make this happen

The Script

Function Get-SCCMDeviceResourceID
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
$SiteServer,
[Parameter(Mandatory=$True)]
$SiteCode,
[Parameter(Mandatory=$True)]
$DeviceName
)

Try{
Get-WmiObject -Namespace "Root\SMS\Site_$($SiteCode)" -Class 'SMS_R_SYSTEM' -Filter "Name='$DeviceName'" -ComputerName $SiteServer
}
Catch{
$_.Exception.Message
}
}

# Configuration and variables #
$Site = "TS1" # SCCM Site name #
$SCCMServer = "localhost" # Server name of the SCCM server #
$CollectionName = "Awesome Collection" # What device collection that should get populated #
$Computers = (get-content "C:\temp\sccm.txt") # Which computers should get added to the Collection #
$SourceIDpath = "C:\temp\sourceid.txt"

Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
Remove-PSDrive -name $Site -force
New-PSDrive -Name $Site -Root $SCCMServer -PSProvider CMSite
Set-Location TS1: # needs to be the same as the $Site variable

If
(test-path $sourceidPath)
{Remove-Item -Path $SourceIDpath -Force}
else {}

Foreach ($Computer in $Computers)
{

$ComputerID = (Get-SCCMDeviceResourceID -SiteCode $Site -SiteServer $SCCMServer -DeviceName $Computer).ResourceId
Out-File -InputObject $ComputerID -FilePath $SourceIDpath -Append

}

$Sourceid = (get-content $SourceIDpath)

Foreach ($node in $Sourceid)

{
Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceId $node
}

Start-sleep -s 60

$SCCMNode = (Get-Content -Path "C:\temp\sccm.txt")

Foreach ($SCCMNodes in $SCCMNode) {

$SCCMClient = [wmiclass] "\\$SCCMNodes\root\ccm:SMS_Client"

try{

# Run Hardware inventory
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000001}");
# Run Machine Policy Evaluation and Update Cycle (Download Machine Policy)
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
# Run Machine Policy Evaluation (Apply Machine Policy)
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000022}");
# Run Software Updates Deployment Evaluation Cycle
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000108}");
# Run Discovery Data Collection Cycle
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000003}");
# Run Hardware inventory cycle
#$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000101}");

}
catch{
$_.Exception.Message;
}
}

 

Disecting the Script

Let me dissect the code i will explain what every part does so if your new to powershell you can modify it to fit your needs,  because there will always be different needs.   The first part is just the function who makes it possible to get the DeviceID from the client. This one you shouldn’t really need to modify.

Function Get-SCCMDeviceResourceID
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
$SiteServer,
[Parameter(Mandatory=$True)]
$SiteCode,
[Parameter(Mandatory=$True)]
$DeviceName
)

Try{
Get-WmiObject -Namespace "Root\SMS\Site_$($SiteCode)" -Class 'SMS_R_SYSTEM' -Filter "Name='$DeviceName'" -ComputerName $SiteServer
}
Catch{
$_.Exception.Message
}
}


Next part is the Configuration and variable part. Here you need to modify the $site, $SCCMServer, $CollectionName variables to fit your environment.

# Configuration and variables #
$Site = "TS1" # SCCM Sitecode name #
$SCCMServer = "localhost" # Server name of the SCCM server #
$CollectionName = "AwesomeCollection" # What device collection that should get populated #
$Computers = (get-content "C:\temp\sccm.txt") # Which computers should get added to the Collection #
$SourceIDpath = "C:\temp\sourceid.txt"

Import-Module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
Remove-PSDrive -name $Site -force
New-PSDrive -Name $Site -Root $SCCMServer -PSProvider CMSite
Set-Location TS1: # Needs to be the same as the $Site
If
 (test-path $sourceidPath)
 {Remove-Item -Path $SourceIDpath -Force}
 else {}

As for $computers you can stick with that as long as you create that .txt file and inputs the computers you want to be added in the device collection or maybe you want to get them directly from AD you can do that for example.

4

as for $sourceIDpath just make sure the C:\temp folder exist, storing the SourceID in the .txt file isn’t the sexiest way of doing it but it works and that’s all that matters here.

And the next part the 2 for each,

first one will call the function to retrieve the ResourceID for the all the computers and put them in to C:\temp\sourceid.txt

and the second one will add the sourceid’s in sourceid.txt in to the Device collection one at the time.

 


Foreach ($Computer in $Computers)

{

$ComputerID = (Get-SCCMDeviceResourceID -SiteCode $Site -SiteServer $SCCMServer -DeviceName $Computer).ResourceId
 Out-File -InputObject $ComputerID -FilePath $SourceIDpath -Append

}

$Sourceid = (get-content $SourceIDpath)

 Foreach ($node in $Sourceid)

{
 Add-CMDeviceCollectionDirectMembershipRule -CollectionName $CollectionName -ResourceId $node
 }

After that we will trigger a 60 second sleep, depending on how many resources you added to the device collection it can take some time for SCCM to process it, 60 seconds is more then enough for a few hounded depending on the performance of the server of course.

Then we get all the computers again and trigger the evaluation that we want, there’s a lot to choose from but the ones in this script are the one i use the most. but if you want to see whats else available here’s one of many posts about it

https://blogs.technet.microsoft.com/charlesa_us/2015/03/07/triggering-configmgr-client-actions-with-wmic-without-pesky-right-click-tools/

if there’s anyone you don’t want to use below, you can easy comment them out with putting a # in front as i have done with the Hardware inventory cycle ending in “101”


Start-sleep -s 60

$SCCMNode = (Get-Content -Path "C:\temp\sccm.txt")

Foreach ($SCCMNodes in $SCCMNode) {

$SCCMClient = [wmiclass] "\\$SCCMNodes\root\ccm:SMS_Client"

try{

# Run Hardware inventory
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000001}");
# Run Machine Policy Evaluation and Update Cycle (Download Machine Policy)
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000021}");
# Run Machine Policy Evaluation (Apply Machine Policy)
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000022}");
# Run Software Updates Deployment Evaluation Cycle
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000108}");
# Run Discovery Data Collection Cycle
$SCCMClient.TriggerSchedule("{00000000-0000-0000-0000-000000000003}");
# Run Hardware inventory cycle
#$SCCMClient.TriggerSchedule(&"{00000000-0000-0000-0000-000000000101}");

}
catch{
$_.Exception.Message;
}
}

When you have done all the changes that’s needed, just run the script and lean back!
5

This scenario assumes that you have already deployed the deployment with the correct device collection. Later on i will go through a full automated process that also includes the deployment. And you could of course turn all this in to a function and just make it even more less manuell labor, but this is just a proof of concept and i want it to be easy to go through.

Thats all for this time, Cheers Timmy