Improved Support for WMI

Improved Support for WMI

  • Comments 15

<Edited 7/2/2006 to add tags and categories>
We have recently completed work on improved support for WMI including:

  1. Improved Adapters for WMI objects and classes
    1. Most notably the ability to easily invoke methods on both
  2. Direct language support for WMI
    1. Type accelerators for [WMI], [WMICLASS], and [WMISEARCHER]

Everyone that uses WMI owes a debt of gratitude to Greg Ramsey.  Greg did an MMS session and lab focused on Scripting SMS using VBscript and Windows PowerShell.  Jim Truher and I joined Greg to host a Birds of a Feather (BOF) session on Scripting.  Greg was quite enthusiastic about the power of Windows PowerShell but during the BOF someone asked him directly, "So which is it - should we be using VBscript or Windows PowerShell to script SMS".  I forgot exactly what Greg said but it was along the line so of, "if you want to do reporting, use Windows PowerShell because it is very powerful but if you want to get things done, use VBScript because you can't invoke WMI methods (at least not easily)".

This was a real wake up call for us.  Greg is exactly the sort of person that we want to be a ardent, unabashed, no reservations, hard core Windows PowerShell user and the message was loud and clear - almost but not quite

We knew that our WMI support was not what we wanted it to be but as I've mentioned many times, to ship is to choose.  We thought that we had reasonable support and that WMI users wouldn't be phased by some of the deficiencies - yes calling methods was complex but we figured that if you were using WMI, you were self-qualified as being able to cope with complexity :-) . 

Just to be precise, you could always call WMI methods but you had to do so using the Invoke_Method() call pass it the name of the Method and then all the parameters encoded as an array.   It was probably total folly to think that this was an acceptable user-experience but it took Greg's comment to get things moving on the right track.

In RC2 this is what a WMI object looks like:

PS> $g=Get-WmiObject Win32_process -filter 'Name = "calc.exe"'
PS> $g |gm -membertype "Method,Property"

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

Name                       MemberType Definition
----                       ---------- ----------
AttachDebugger             Method     System.Management.ManagementBaseOb...
GetOwner                   Method     System.Management.ManagementBaseOb...
GetOwnerSid                Method     System.Management.ManagementBaseOb...
SetPriority                Method     System.Management.ManagementBaseOb...
Terminate                  Method     System.Management.ManagementBaseOb...
__CLASS                    Property   System.String __CLASS {get;}
__DERIVATION               Property   System.String[] __DERIVATION {get;}
__DYNASTY                  Property   System.String __DYNASTY {get;}
__GENUS                    Property   System.Int32 __GENUS {get;}
__NAMESPACE                Property   System.String __NAMESPACE {get;}
__PATH                     Property   System.String __PATH {get;}
__PROPERTY_COUNT           Property   System.Int32 __PROPERTY_COUNT {get;}
__RELPATH                  Property   System.String __RELPATH {get;}

Notice that the Methods are now the WMI methods for that particular WMIObject (and not the Methods for WMI).  If you want those, you can still get them using PSBASE (Remember - PSBASE is the way to bybass our type Adapter and get an the native capabilities of an object).

PS> $g.psbase |gm -membertype Method

   TypeName: System.Management.Automation.PSMemberSet

Name                      MemberType Definition
----                      ---------- ----------
add_Disposed              Method     System.Void add_Disposed(EventHandl...
Clone                     Method     System.Object Clone()
CompareTo                 Method     System.Boolean CompareTo(Management...
CopyTo                    Method     System.Management.ManagementPath Co...
CreateObjRef              Method     System.Runtime.Remoting.ObjRef Crea...
Delete                    Method     System.Void Delete(), System.Void D...
Dispose                   Method     System.Void Dispose()
Equals                    Method     System.Boolean Equals(Object obj)
Get                       Method     System.Void Get(), System.Void Get(...
get_ClassPath             Method     System.Management.ManagementPath ge...
get_Container             Method     System.ComponentModel.IContainer ge...
get_Item                  Method     System.Object get_Item(String prope...
get_Options               Method     System.Management.ObjectGetOptions ...
get_Path                  Method     System.Management.ManagementPath ge...
get_Properties            Method     System.Management.PropertyDataColle...
get_Qualifiers            Method     System.Management.QualifierDataColl...
get_Scope                 Method     System.Management.ManagementScope g...
get_Site                  Method     System.ComponentModel.ISite get_Site()
get_SystemProperties      Method     System.Management.PropertyDataColle...
GetHashCode               Method     System.Int32 GetHashCode()
GetLifetimeService        Method     System.Object GetLifetimeService()
GetMethodParameters       Method     System.Management.ManagementBaseObj...
GetPropertyQualifierValue Method     System.Object GetPropertyQualifierV...
GetPropertyValue          Method     System.Object GetPropertyValue(Stri...
GetQualifierValue         Method     System.Object GetQualifierValue(Str...
GetRelated                Method     System.Management.ManagementObjectC...
GetRelationships          Method     System.Management.ManagementObjectC...
GetText                   Method     System.String GetText(TextFormat fo...
GetType                   Method     System.Type GetType()
InitializeLifetimeService Method     System.Object InitializeLifetimeSer...
InvokeMethod              Method     System.Object InvokeMethod(String m...
Put                       Method     System.Management.ManagementPath Pu...
remove_Disposed           Method     System.Void remove_Disposed(EventHa...
set_Item                  Method     System.Void set_Item(String propert...
set_Options               Method     System.Void set_Options(ObjectGetOp...
set_Path                  Method     System.Void set_Path(ManagementPath...
set_Scope                 Method     System.Void set_Scope(ManagementSco...
set_Site                  Method     System.Void set_Site(ISite value)
SetPropertyQualifierValue Method     System.Void SetPropertyQualifierVal...
SetPropertyValue          Method     System.Void SetPropertyValue(String...
SetQualifierValue         Method     System.Void SetQualifierValue(Strin...
ToString                  Method     System.String ToString()

But now that the Instance properties are exposed, WMI objects act more like "normal" objects:

PS> $g.GetOwner()
__GENUS          : 2
__CLASS          : __PARAMETERS
__RELPATH        :
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
Domain           : NTDEV
ReturnValue      : 0
User             : jsnover

PS> $g.Terminate()
__GENUS          : 2
__CLASS          : __PARAMETERS
__RELPATH        :
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0


We have also changed the Adapted view of WMI Classes.  These used to share the same adapter as WMI Instances which meant that you saw instance properties, which makes no sense.  Here is what a WMI Class now looks like:

$c  = Get-WmiObject -list |where {$_.Name -eq "Win32_Process"}
PS> $c |Format-List *

Name             : Win32_Process
__GENUS          : 1
__CLASS          : Win32_Process
__SUPERCLASS     : CIM_Process
__DYNASTY        : CIM_ManagedSystemElement
__RELPATH        : Win32_Process
__DERIVATION     : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemEleme
__SERVER         : JPSLAP04
__NAMESPACE      : ROOT\cimv2
__PATH           :

PS> $c | Get-Member -MemberType Method
   TypeName: System.Management.ManagementClass#ROOT\cimv2\Win32_Process

Name   MemberType Definition
----   ---------- ----------
Create Method     System.Management.ManagementBaseObject Create(System.S...

And you can use it just as you would expect

PS> $c.Create("Calc.exe")
__GENUS          : 2
__CLASS          : __PARAMETERS
__RELPATH        :
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ProcessId        : 2948
ReturnValue      : 0



In addition to these, we decided to add direct language support for WMI into Windows PowerShell. 

[WMISEARCHER] is a type accelerator for a ManagementObjectSearcher. It can take a string constructor to create a searcher that you can then do a GET() on:

PS> $s = [WmiSearcher]'Select * from Win32_Process where Handlecount > 1000'

PS> $s.Get() |sort handlecount |ft handlecount,__path,name -auto

handlecount __PATH                                            name
----------- ------                                            ----
\\JPSLAP04\root\cimv2:Win32_Process.Handle="3724" powershell...
\\JPSLAP04\root\cimv2:Win32_Process.Handle="1388" winlogon.exe
\\JPSLAP04\root\cimv2:Win32_Process.Handle="2852" iexplore.exe
\\JPSLAP04\root\cimv2:Win32_Process.Handle="1204" OUTLOOK.EXE
\\JPSLAP04\root\cimv2:Win32_Process.Handle="1912" iexplore.exe
\\JPSLAP04\root\cimv2:Win32_Process.Handle="1768" svchost.exe


[WMI] is a type accelerator for ManagementObject. This has a string constructor taking a local or absolute WMI Path to a WMI instace and returning a object bound to that instance:

PS> $p = [WMI]'\\JPSLAP04\root\cimv2:Win32_Process.Handle="1204"'
PS> $p.Name


[WMICLASS] is a type accelerator for ManagementClass. This has a string constructor taking a local or absolute WMI Path to a WMI class and returning a object bound to that class:

PS> $c = [WMICLASS]"root\cimv2:WIn32_Process"
PS> $c |fl *

Name             : Win32_Process
__GENUS          : 1
__CLASS          : Win32_Process
__SUPERCLASS     : CIM_Process
__DYNASTY        : CIM_ManagedSystemElement
__RELPATH        : Win32_Process
__DERIVATION     : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemEleme
__SERVER         : JPSLAP04
__NAMESPACE      : ROOT\cimv2
__PATH           :

We think that these changes make Windows PowerShell THE best environment to use and script WMI.  When RC2 comes out towards the end of the summer, you'll be able to kick the tires on these new features and let us know if you agree. 

I want to highlight the role of user feedback in these changes.  If it wasn't for Greg speaking up and giving us honest feedback about where we were not doing a good enough job, these changes would not have been made.  So hat's off to Greg but also - if there is something about Windows PowerShell that you don't like - let us know - we really are listening.


Jeffrey Snover
Windows PowerShell Architect

PSMDTAG:FAQ: How do i invoke a method on a WMI class?
PSMDTAG:FAQ: How do i invoke a method on a WMI object?
PSMDTAG:FAQ: How can I use WQL?
PSMDTAG:FAQ: How do I use WMI?
PSMDTAG:FAQ: How do I bind to a WMI Instance from a WMI PATH?
PSMDTAG:TYPE:WMI  Invoking methods

Leave a Comment
  • Please add 2 and 7 and type the answer here:
  • Post
  • I agree.  This will make PS the obvious choice for any serious scripting of WMI.

    When ADSI comes in we will be most pleased.
  • PS> $c = [WMICLASS]"root\cimv2:WIn32_Process"

    I like this RC2 WMI syntax, very short and sweet.

    Currently I use this to get a list of BizTalk Hosts.

    $BTSHosts = get-wmiobject -class "MSBTS_HostSetting" -namespace "root\MicrosoftBizTalkServer"

  • PS should implement most of the general  data you can get (e.g., machine settings, software settings, etc) using WMI with native PowerShell objects/commands.  PowerShell native objects would be singnficantly less prone to be legacy code/functionaltiy than using WMI via powershell.
  • Great Post jps! I'm excited to see RC2 . . .:)

    Greg Ramsey
  • Thanks to you Greg!

    Jeffrey Snover [MSFT]
    Windows PowerShell/Aspen Architect
    Visit the Windows PowerShell Team blog at:
    Visit the Windows PowerShell ScriptCenter at:
  • I wonder why

     get-wmiobject -class win32_scheduledjob

    doesn't return an object, although scheduled tasks exist on the machine and the class "win32_scheduledjob" is listed by

     get-wmiobject -list

  • I repeat the same question asked by Charlie on Nov 01 2006.

    get-wmiobject -class "Win32_Service" -namespace "root\cimv2" -computername .

    My above script to access Scheduled Jobs. Howvere I don't any objects returned.

  • Is there a way third party can implement this dynamic cmdlet like WMI object?

    Current cmdlet samples are all static interface.

  • if scheduled jobs were created not using wmi, you won't see them in wmi.  look up win32_scheduledjob in msdn for the details.

  • Hi I am getting the following error on my script when i try it on remote servers.

    The Object exporter specified was not found.

    Is there anyway to resolve this issue.



  • Why is there never VC++ examples described.

    WMI is great integrated in our application, the DCOM API works fine, but is not as documented as you would hope.

    Maybe it will come.

    In the meantime, I have found a good and detailed example at:

    It seems C++ developers are a dying breed.

  • Why is there never VC++ examples described.

    WMI is great integrated in our application, the DCOM API works fine, but is not as documented as you would hope.

    Maybe it will come.

    In the meantime, I have found a good and detailed example at:

    It seems C++ developers are a dying breed.

  • PSMDTAG:FAQ: What is a TYPE SHORTCUT? PSMDTAG:FAQ: What are the TYPE SHORTCUTS? Type shortcuts are a

  • A sneak peak at new stuff in WMI in Windows 7. (Continuation of WMI - The story so far ) WMI, Powershell

Page 1 of 1 (15 items)