Skip to main content

PowerShell + SCCM 2012 R2: Get the Device/ User Info WMI Way

This is in continuation of my last post on Using PowerShell to get client information  
In this post will be exploring on the ways to do the same thing using WMI/CIM, Why ?
With WQL syntax we can ask for only the properties we need rather than getting everything back.

The post will cover 3 topics:
  1. Query individual Device in CM using WMI/CIM
  2. Query Members of a Device Collection using WMI/CIM
  3. Query Users in a User Collection using WMI/CIM
To get the number of properties got back from a call to Get-CMDevice use Get-Member and Measure-Object like below:


Most of the properties returned back may be empty depending on how you are using ConfigMgr e.g if you use endpoint protection than those attributes in the class will be populated else will be empty.

Now if you see the output of Get-CMDevice is actually is a result of the SMS_CombinedDeviceResources



Let me tell you a little secret :-$ ...if you are looking forward to explore WMI part of ConfigMgr and have a doubt on which Class to look for, then piping the output of the Cmdlets with the ConfigurationManager Module to Get-Member gives you a hint.

The cmdlets shipped with (written in C#) the Module essentially makes WMI calls and then expose the results back to us that's why IResultObject in the Typename (above screenshot) :-B


So let's explore a bit the SMS_CombinedDeviceResources class...using the Get-CIMClass cmdlet.

Note - will be using the $PSDefaultParameters as mentioned in my earlier posts to set the Computername and Namespace parameter to point to the ConfigMgr Server.

We can see a lot of properties defined in this class:



Query individual Device using WMI/CIM


To get this information for a client can be a simple WMI call where you specify a filter for the Name property like below:


Get-CimInstance -ClassName SMS_CombinedDeviceResources -Filter 'Name="DEXTERDC"'

But the good thing about using the WMI/ CIM cmdlets directly is that we can use the WQL query to select only the properties we want (see below):


Get-CimInstance -Query "Select Name,LastMPServerName,deviceos from SMS_CombinedDeviceResources where Name='DexterDC'"

Note that all the extra properties show up as blank (other than those specified with Select statement), this will save the network bandwidth and will be efficient when we are processing say hundreds or thousands of clients.


Query Members of a Device Collection using WMI/CIM

If you have read few of my earlier posts then you would know that all the collections we create are an instance of the class SMS_Collection. So let's go ahead and do a WMI query to get the object back for the "All Systems" collection.

 Get-CimInstance -ClassName SMS_Collection -Filter 'Name="All Systems"'

Now out of all the properties listed the one which stands aside is the property named 'MemberClassName'. If you query this Class mentioned in the property MemberClassName then you get back all the members of the collection..I think you figured that out already ;)

Below is the value of the property MemberClassName for my "All Systems" collection
PS> (Get-CimInstance -ClassName SMS_Collection -Filter 'Name="All Systems"').MemberClassName

SMS_CM_RES_COLL_SMS00001

So let's do a WMI Call for this class:



You can see it got all the machines which were member of the 'All Systems' Collection

Now using the WQL query to optimize this a bit :


Get-CimInstance -query 'Select Name,IsClient,LastMPServerName,DeviceOS from SMS_CM_RES_COLL_SMS00001' | select -Property Name,IsClient,LastMPServerName,DeviceOS

I pipe it to the Select-Object cmdlet to get the properties I wanted as rest every property is empty.

To give an idea on the efficiency part see below:


PS> Measure-Command {  Get-CMDeployment -CollectionName 'All Systems'}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 55
Ticks             : 10554314
TotalDays         : 1.22156412037037E-05
TotalHours        : 0.000293175388888889
TotalMinutes      : 0.0175905233333333
TotalSeconds      : 1.0554314
TotalMilliseconds : 1055.4314



PS> Measure-Command  {Get-CimInstance -query 'Select Name,IsClient,LastMPServerName,DeviceOS from SMS_CM_RES_COLL_SMS000
01' }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 173
Ticks             : 1738179
TotalDays         : 2.01178125E-06
TotalHours        : 4.828275E-05
TotalMinutes      : 0.002896965
TotalSeconds      : 0.1738179
TotalMilliseconds : 173.8179



This is pretty explanatory right ! This would be pretty significant difference if there are a lot of members in the Collection.


Query Users in a User Collection using WMI/CIM

Now there are User Collections too so how do we query the members in it. Well easy the same way we did it with Device Collections. :P

Well the difference is in the type of collection:
PS> (Get-CimInstance -ClassName SMS_Collection -Filter 'Name="All Systems"').CollectionType
2
PS> (Get-CimInstance -ClassName SMS_Collection -Filter 'Name="All Users"').CollectionType
1
So if we wanted to get the members of the collection "All Users" then below is a one liner to do that:

Get-CimInstance -ClassName  (Get-CimInstance -ClassName SMS_Collection -Filter 'Name="All Users"').MemberClassName |

 Select Name,SMSID

You can see the Class to which a User in CM belongs is SMS_CombinedUserResources which has few properties defined in it. 


[UPDATE} I was writing a function which will do all of the above things shown for me..there is a switch by the name $PropertySelect (also when I tried using $SelectProperty it gave me an error saying that 'The parameter name "SelectProperty" is reserved for future use.' ) which will give an option to select properties in Out-Gridview Window and these properties will only be retrieved ..pretty cool B-)
That's it for today's post. :) :)

Popular posts from this blog

Test connectivity via a specific network interface

Recently while working on a Private cloud implementation, I came across a scenario where I needed to test connectivity of a node to the AD/DNS via multiple network adapters.  Many of us would know that having multiple network routes is usually done to take care of redundancy. So that if a network adapter goes down, one can use the other network interface to reach out to the node. In order to make it easy for everyone to follow along, below is an analogy for the above scenario: My laptop has multiple network adapters (say Wi-Fi and Ethernet) connected to the same network. Now how do I test connectivity to a Server on the network only over say Wi-Fi network adapter?

PowerShell + SCCM : Run CM cmdlets remotely

Today I saw a tweet about using implicit remoting to load the Configuration Manager on my machine by Justin Mathews . It caught my eye as I have never really tried it, but theoretically it can be done. Note - The second tweet says "Cannot find a provider with the name CMSite", resolution to which is in the Troubleshooting section at the end.

PowerShell : Trust network share to load modules & ps1

Problem Do you have a central network share, where you store all the scripts or PowerShell modules ? What happens if you try to run the script from a network share ? or if you have scripts (local) which invoke scripts or import PowerShell modules stored on this network share ? Well you would see a security warning like below (Note - I have set execution policy as 'Unrestricted' not 'bypass' here): Run a .ps1 from the network share Well this is a similar warning, which you get when you download scripts from Internet. As the message says run Unblock-File cmdlet to unblock the script and then run it, let's try it.