Use WMI and PowerShell to Create Collection Query Rules
Summary: Microsoft PFE, Heath Lawson, talks about using Windows PowerShell and WMI to create collection query rules.
Microsoft Scripting Guy, Ed Wilson, is here. Heath Lawson is back with us today for Part 3 in his series. You can catch up by reading Part 1 and Part 2:
- Apply Common PowerShell Concepts to Configuration Manager
- Use PowerShell to Set Configuration Manager Properties
Howdy y’all! Heath here. This is the last in a series of three posts about Windows PowerShell for System Center Configuration Manager Administrators.
This session is going to be a bit different because we’re not going to use the built-in Configuration Manager cmdlets.
“But Heath,” you say, “I know nothing else. These Configuration Manager cmdlets you showed us in the last session are priceless, and I can’t imagine my life without them!”
I know how you feel, and fear not, we’re going to dig in a bit, and I’ll show you a few methods (no pun intended) that are even more powerful than the built-in Configuration Manager cmdlets!
Let’s start with some background knowledge. Configuration Manager is heavily reliant on Windows Management Instrumentation (WMI) to allow interaction with Configuration Manager data. On the client side, almost all Configuration Manager information (such as policies and content locations) are stored in WMI.
On the server side of the house, we make extensive use of WMI via a special role called the SMS Provider. The purpose of the SMS Provide is to interact with the database and translate between WMI Query Language (WQL) and SQL. All of our security is enforced by the SMS Provider, and it’s where all of our consoles connect to perform administrative functions. Starting in Configuration Manager 2012, we can have multiple SMS Providers per site, which is useful if we are making heavy use of the SMS Provider through automation.
Functionally, the SMS Provider organizes objects into WMI classes, with each class representing a different type of information for Configuration Manager. In Configuration Manager, there are classes for collections, software update groups, individual PCs, task sequence steps—you name it, and there is a class for it.
One really handy tip for folks looking to gain a deeper understanding of Configuration Manager is to look at SMSProv.log. This log will give us a good idea about the WMI query we’re executing and what classes and methods are used for various operations within the console.
The SMS Provider is comprised of a single primary name space that we want to connect to: root\sms\site_<sitecode>. In the following examples, you’ll see that I am using site P35 again. If you’re following along in your lab, make sure that you change the examples to match your site code. You’ll also see that I have a server name specified, and you’ll want to change that to reflect your lab server’s name.
I’d like to pause for a second and provide an awesome link that most folks I talk with aren’t aware exists: System Center 2012 R2 Configuration Manager SDK. Why is the SDK important? Well, without the previous knowledge, most folks don’t know that most of our publically provided code examples make use of the documented WMI calls that are available via the SDK, so understanding how to interact with different objects is hugely important!
Using native WMI to create collection query rules
In this session, we’re going to use native WMI to perform the same steps as last time, except we’re going to go a step further and add a collection query rule this time. Sure, we could use New-CMDeviceCollection, Add-CMDeviceCollectionQueryMembershipRule, and New-CMSchedule to set it, but where’s the fun in that?
Let’s get started. I’m going to introduce something you may not have used in the past: type accelerators. A type accelerator is a “shortcut” of sorts to a .NET managed class. This means that instead of having to do a bunch of funky coding, I can get access directly in Windows PowerShell to .NET WMI methods. Let’s give it a go:
$CMCollection = ([WMIClass]”\\LDCM01\root\sms\site_P35:SMS_Collection”).CreateInstance()
That might look like a funky bit of Windows PowerShell, but allow me to break it down…
First, we’re creating a new object of the WMIClass type: NewCMCollection. We are then assigning a new instance of the SMS_Collection class. So, I just created a new object that represents a new collection. Easy, huh?
Now, if we pull all the properties and methods by using Get-Member, we can see that much more is exposed than we saw last time when we used New-CMDeviceCollection:
So, very much like the last module, we see a number of properties are available for us to configure. However, you’ll see that we have additional methods available. These will change from WMI class to WMI class, but this should give you an idea of how Configuration Manager exposes common functionality.
A great resource for all of this information is the Configuration Manager SDK. If we take a look at SMS_Collection Server WMI Class, we can see the same data documented and ready for consumption.
So, like in the last example, we are going to set some properties on our new collection. Let’s give it a name and a comment:
$CMCollection.Name = “All Windows 2012 R2 Devices”
$CMCollection.Comment = “This collection contains all Windows Server 2012 R2 Devices”
$CMCollection.LimitToCollectionID = “SMS00001”
$CMCollection.RefreshType = 2
Before we get too much further, we need to commit the work we’ve done. Like the previous example, we’ll call the Put() method to commit our new collection:
Now that we’ve done that, let’s dive a bit further. What good is a collection without any members? To get resources in this collection, we’ll add a Membership rule…
But wait! We need to create a rule to pass it. In this case, it is asking for an object of the SMS_CollectionRule class. Let’s create one using our new-found knowledge:
$CMRule = ([WMIClass]”\\LDCM01\root\sms\site_P35:SMS_CollectionRuleQuery”).CreateInstance()
$CMRule.QueryExpression=”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 inner join SMS_G_System_OPERATING_SYSTEM on SMS_G_System_OPERATING_SYSTEM.ResourceId = SMS_R_System.ResourceId where SMS_G_System_OPERATING_SYSTEM.Caption = `"Microsoft Windows Server 2012 R2 Datacenter`"”
$CMRule.RuleName = “Windows Server 2012”
Now, I have a CollectionRuleQuery object that represents a query-based collection rule. With this, I can set a few properties, namely the QueryExpression, QueryID, and RuleName properties:
With my new found query rule, I can add it to the collection:
Great! Now, for the final step. We’ll set a refresh schedule so the query updates on a recurring schedule. Schedule tokens are used in several places in Configuration Manager, such as collections and maintenance windows. To set a refresh schedule, we need to create a schedule token:
$CMSchedule = ([WMIClass]"\\LDCM01\Root\sms\site_P35:SMS_ST_RecurInterval").CreateInstance()
$CMSchedule.DaySpan = “1”
$CMSchedule.StartTime = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).ToString())
Now that I have a schedule token, I can use it to set the RefreshSchedule property:
Like in previous examples, I need to commit these changes one last time by calling the Put() method.
As you can see, we now have a collection with a query-based rule and a refresh schedule:
In this session, we created a collection with a query rule and a refresh schedule. You can easily adapt this to set other options or create maintenance windows…the sky is the limit.
As these sessions are coming to a close, my intent was to give each of you the knowledge to more effectively script and automate against Configuration Manager. Hopefully I’ve held up my end of the bargain, and please let me know in the following Comments box!
Thanks for an engaging series, Heath!
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at email@example.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy