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
In to the awesome device collection, awesome collection!
when that’s done we want the client to trigger the defined evaluation we need,
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.
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
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!
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
Trigger-BLEvaluation – SCCM 2012 R2. Looking for This same powershell script for this one. But, I need one for “all systems” for SCCM. Can you help me with that. Thank you very much! I’m not a powershell scripter at all. But, getting all more baselines in compliance and now having to manually force to evaluate is a pain.. In my environment I have 44,000 devices.. and I have 15 baselines that I need to be in compliance. Thank you very much! Karen
function Trigger-BLEvaluation
{
param (
[String][Parameter(Mandatory=$true, Position=1)] $ComputerName,
[String][Parameter(Mandatory=$False, Position=2)] $BLName
)
If ($BLName -eq $Null)
{
$Baselines = Get-WmiObject -ComputerName $ComputerName -Namespace rootccmdcm -Class SMS_DesiredConfiguration
}
Else
{
$Baselines = Get-WmiObject -ComputerName $ComputerName -Namespace rootccmdcm -Class SMS_DesiredConfiguration | Where-Object {$_.DisplayName -like $BLName}
}
$Baselines | % {
([wmiclass]”\$ComputerNamerootccmdcm:SMS_DesiredConfiguration”).TriggerEvaluation($_.Name, $_.Version)
}
}
Hey Karen, Yeah sure i can help you out with that. To be able to explain it properly i will make a blog post about it. Will link it to you as soon as it’s done. //Timmy
https://timmyit.com/2016/09/27/qa-trigger-baseline-evaluation-on-a-device-collection/
Hi Timmy, Thanks for the blog that is really useful for me.
also i need to perform the counts of the check that specific baseline is doing. Actually i am getting many mismatch of the counts from SCCM side and from the client side.
i have approx 10k server where getting this issue. not sure i can do this using powershell or not (initially i need to do the count of the checks )
Please help if we have anything to do the count of checks.
Thanks in Advance