Learn about Windows PowerShell
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:
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!
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
Great Post ! showing alternate routes to depending on Cmdlets. WMI is the Key !I must add the same automation can be achieved in ConfigMgr 07 too.....we created a Tool running PowerShell scripts which will edit the Query Membership Rules to add a machine name to a collection and update it. Simplified our deployment process :)Uploaded the Script in Technet gallery too.http://gallery.technet.microsoft.com/Add-MachineToSCCMQueryRule-0cbac1e1
DexterPOSH, Thanks for the comment! I love hearing examples of automation! Very true, and I should have pointed it out in the article, this approach will work with older versions of Configuration Manager as well.Heath
HeathAm amazed at the possibilities of automation possible by leveraging WMI with PowerShell.It has been a real eye opener , experimenting with it a lot. Read few cool posts of yours which gave me an idea of few more things to automate :)RegardsDexter
Is there any way in power shell to find out a particular webpage accessing from where and all currently[Worldwide?]?
What about updating a query? Rather than delete and add, is it possible to update?
very informative post thanks for share.
I keep getting Exception calling "AddMembershipRule" : "Not found ". Any ideas? I ran Get-Member on my $CMCollection and the method is listed, but it just won't run >_<