Skip to main content

PowerShell + WMI - Static & Instance Methods

One has to get their feet wet with WMI when it comes to managing ConfigMgr with PowerShell. How ConfigMgr uses WMI ? Not only ConfigMgr but for other products if you leverage WMI with PowerShell then understanding what are Static & Instance methods is important.

But there are lot of places where People stumble ( I did too ). Below is a question asked in Hyderabad PowerShell User Group (PSHUG) showing one of the common point of confusion.



If you are a ConfigMgr Admin then you already know that in SCCM client we have a lot many Client actions that can be triggered remotely. Below are the available SCCM Client actions (In CM 2012) :





Going back to the question, below code will work,which is triggering "Software Inventory" on a remote $machine:


001
002
$Client1 = $([WmiClass]"\\$Machine\ROOT\ccm:SMS_Client")
$Client1.TriggerSchedule("{00000000-0000-0000-0000-000000000021}")

One can get more info on the class SMS_Client & TriggerSchedule Method.

But why are we not able to see the method when we do the below:


001
002
$Client2 = Get-WmiObject -ComputerName $Machine -Namespace root\ccm -Class SMS_Client
$Client2 | Get-Member -MemberType *

Note - There are two variables $Client1 & $Client2 


Before we go further would like to clarify one thing first, one can get the WMI Class Object by using the Get-WMIObject cmdlet itself with -List switch

So If I do the below..take note of the -List switch at the end:

001
$Client3 = Get-WmiObject -Class SMS_client -Namespace Root\CCM -ComputerName $machine -List


Go ahead and see for yourself that the two objects $Client1 and $Client3 are essentially the same :) 

The answer to why the TriggerSchedule method doesn't appear when we pipe it to Get-Member is really simple, Just compare the Type of both the Objects you have at hand



So from above we deduce that those two are essentially 2 different objects so you won't find the TriggerSchedule Method on the $Client2 ;)

This becomes obvious if we think over it --> [WmiClass] type accelerator gives you the WMI Class Object back not the WMI Instance


Detailed Explanation


To clarify things a bit more the Class ($Client1) is a definition of Objects and Instance (Client2) is the manifestation of the class. 

In our question $Client1 is Class and $Client2 is an Instance of the class.

Now a class can have 2 type of methods : 

  1. Static Methods (only available on the class)
  2. Instance Methods (available on the Instances of the class)

So how do we go on getting this key piece of information, whether it is a Static method or not ?

Once you have the class object ($Client1 ) you can explore it. 

So once we have the WMI Class Object we can do the below to take a look at the methods and the qualifiers:
PS> $Client1 | select -ExpandProperty methods | select name,qualifiers

Name                                                        Qualifiers
----                                                        ----------
ResetPolicy                                                 {implemented, static}
RequestMachinePolicy                                        {implemented, static}
EvaluateMachinePolicy                                       {implemented, static}
TriggerSchedule                                             {implemented, static}
RepairClient                                                {implemented, static}
SetAssignedSite                                             {implemented, static}
GetAssignedSite                                             {implemented, static}
SetGlobalLoggingConfiguration                               {implemented, static}
ResetGlobalLoggingConfiguration                             {implemented, static}
SetClientProvisioningMode                                   {implemented, static}

Notice that all the methods on the class are static.




To sum it all let's take a class having both Static and Instance method e.g Win32_Share

PS> Get-WmiObject -Class WIn32_Share -List| select  -ExpandProperty methods | select name,qualifiers

Name                                                        Qualifiers
----                                                        ----------
Create                                                      {Constructor, Implemented, MappingStrings, Static}
SetShareInfo                                                {Implemented, MappingStrings}
GetAccessMask                                               {Implemented, MappingStrings}
Delete                                                      {Destructor, Implemented, MappingStrings}


So the only method which is static is the Create Method and rest are Static.

Verify this is correct by getting the WMI Instances back and using the Get-Member


PS> Get-WmiObject -Class WIn32_Share  | Get-Member -MemberType method -Force


   TypeName: System.Management.ManagementObject#root\cimv2\Win32_Share

Name          MemberType Definition
----          ---------- ----------
Delete        Method     System.Management.ManagementBaseObject Delete()
GetAccessMask Method     System.Management.ManagementBaseObject GetAccessMask()
SetShareInfo  Method     System.Management.ManagementBaseObject SetShareInfo(System.UInt32 MaximumAllowed, System.St...


Notice that the Create method doesn't show up on the WMI Instance cause it is a static method on the class :)

But it does show up on the WMI Class Object


PS> Get-WmiObject -Class win32_Share -ComputerName $Machine -List | Get-Member -MemberType Method


   TypeName: System.Management.ManagementClass#ROOT\cimv2\Win32_Share

Name   MemberType Definition
----   ---------- ----------
Create Method     System.Management.ManagementBaseObject Create(System.String Path, System.String Name, System.UInt3...


I will be presenting a session on the next PSBUG + BITPro meet on the topic
"PowerShell + ConfigMgr - Getting Started" on 19th July, in this session will shed light on this too. The registrations haven't opened yet. So you can keep an eye on the FB group links.

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.