<Edited 7/2/2006 to add tags and categories>
We have recently completed work on improved support for WMI including:
- Improved Adapters for WMI objects and classes
- Most notably the ability to easily invoke methods on both
- Direct language support for WMI
- 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
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 3
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
Domain : NTDEV
ReturnValue : 0
User : jsnover
PS> $g.Terminate()
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__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:
PS> $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
__PROPERTY_COUNT : 45
__DERIVATION : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemEleme
nt}
__SERVER : JPSLAP04
__NAMESPACE : ROOT\cimv2
__PATH : \\JPSLAP04\ROOT\cimv2:Win32_Process
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
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 2
__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
———– —— —-
1105 \\JPSLAP04\root\cimv2:Win32_Process.Handle=”3724” powershell…
1132 \\JPSLAP04\root\cimv2:Win32_Process.Handle=”1388” winlogon.exe
1495 \\JPSLAP04\root\cimv2:Win32_Process.Handle=”2852” iexplore.exe
1699 \\JPSLAP04\root\cimv2:Win32_Process.Handle=”1204” OUTLOOK.EXE
1719 \\JPSLAP04\root\cimv2:Win32_Process.Handle=”1912” iexplore.exe
2579 \\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
OUTLOOK.EXE
[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
__PROPERTY_COUNT : 45
__DERIVATION : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemEleme
nt}
__SERVER : JPSLAP04
__NAMESPACE : ROOT\cimv2
__PATH : \\JPSLAP04\ROOT\cimv2:Win32_Process
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.
Enjoy!
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 [WMI] [WMICLASS] [WMISEARCHER]
PSMDTAG:TYPE:WMI Invoking methods
0 comments