Tuesday, December 30, 2008

PowerShell’s [WMICLASS] Type accelerator

In January of this year, I wrote a basic article on PowerShell’s WMI Type Accelerators. A type accelerator is, in effect,a shortcut to some underlying .NET component. PowerShell comes with three type accellerators for WMI:

  • [WMI] – a shortcut way of getting to a single instance of a class. I described this type accellerator in an article in February.
  • [WMICLASS] – a short cut to a WMI Class definition to enable access to the class’s static properties and methods. I describe this type accelerator below.
  • [WMISEARCHER] – a short cut to .NET’s ManagementObjectSearcher enabling you to search for objects easily. This type accellerator is an opportunity for a future article.

The [WMICLASS] type accelerator takes a string containing a relative or absolute path to an WMI class, and returns a a System.Management.ManagementClass object that represents the specified class (as opposed to an occurance of that class). For example let’s take a look at the Win32_Share WMI Class. First, look at what Get-WMIObject returns, then look at what the [WMICLASS] type accelerator returns:

 PS c:\foo:\> Get-WMIOBjecct Win32_share | get-memberm

  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.String Descr...
AccessMask          Property     System.UInt32 AccessMask {get;set;}
AllowMaximum        Property     System.Boolean AllowMaximum {get;set;}
Caption             Property     System.String Caption {get;set;}
Description         Property     System.String Description {get;set;}
InstallDate         Property     System.String InstallDate {get;set;}
MaximumAllowed      Property     System.UInt32 MaximumAllowed {get;set;}
Name                Property     System.String Name {get;set;}
Path                Property     System.String Path {get;set;}
Status              Property     System.String Status {get;set;}
Type                Property     System.UInt32 Type {get;set;}
__CLASS             Property     System.String __CLASS {get;set;}
__DERIVATION        Property     System.String[] __DERIVATION {get;set;}
__DYNASTY           Property     System.String __DYNASTY {get;set;}
__GENUS             Property     System.Int32 __GENUS {get;set;}
__NAMESPACE         Property     System.String __NAMESPACE {get;set;}
__PATH              Property     System.String __PATH {get;set;}
__PROPERTY_COUNT    Property     System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH           Property     System.String __RELPATH {get;set;}
__SERVER            Property     System.String __SERVER {get;set;}
__SUPERCLASS        Property     System.String __SUPERCLASS {get;set;}
PSStatus            PropertySet  PSStatus {Status, Type, Name}
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();
ConvertToDateTime   ScriptMethod System.Object ConvertToDateTime();

PS c:\foo:\> [WMICLASS]'Win32_share' | get-member

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

Name                MemberType    Definition
----                ----------    ----------
Name                AliasProperty Name = __Class
Create              Method        System.Management.ManagementBaseObject Create(System.String Path, System.String Name, System.UInt32 ...
__CLASS             Property      System.String __CLASS {get;set;}
__DERIVATION        Property      System.String[] __DERIVATION {get;set;}
__DYNASTY           Property      System.String __DYNASTY {get;set;}
__GENUS             Property      System.Int32 __GENUS {get;set;}
__NAMESPACE         Property      System.String __NAMESPACE {get;set;}
__PATH              Property      System.String __PATH {get;set;}
__PROPERTY_COUNT    Property      System.Int32 __PROPERTY_COUNT {get;set;}
__RELPATH           Property      System.String __RELPATH {get;set;}
__SERVER            Property      System.String __SERVER {get;set;}
__SUPERCLASS        Property      System.String __SUPERCLASS {get;set;}
ConvertFromDateTime ScriptMethod  System.Object ConvertFromDateTime();
ConvertToDateTime   ScriptMethod  System.Object ConvertToDateTime();

In this example, you can see that Get-WMIObject returns System.Management.ManagementObject objects, while [WMICLASS} returns System.Management.ManagementClass objects – in other words, different object types with different members. I note that the MSDN library documentation does not really differentiate static and object members clearly – so you just have to know which is which when dealing with WMI classes.

The object occurrences returned from Get-WMIObject contain three methods: Delete, GetAccessMask and SetShareInfo. These three methods operate on a particular occurrence, i.e. Delete means “delete this occurrence”. However, the object returned from [WMICLASS} both contains none of those three dynamic methods, but does create a static method: Create, i.e. create a new share.

Why bother with [WMICLASS] you might ask. The answer is simple: to access the static methods and properties/fields that the class exposes. In the case of theWin32_Share class, the class has a static method (create) and three dynamic methods( delete, GetAccessMask and SetShareInfo). If you want to create a new share, then use [WMICLASS] to get access to the create method. You can get access to the Delete method by getting the appropriate method. This bit of code illustrates this:

  1. <# 
  2. .SYNOPSIS 
  3.     Demonstrates WMI and Win32_Share 
  4. .DESCRIPTION 
  5.     This script looks at objects retured from Get-WMIObject, and [WMICLASS] and demonstrates 
  6.     the use of a static method (create) and a dynamic or object method (delete).  
  7. .NOTES 
  8.     Author   : Thomas Lee - tfl@psp.co.uk 
  9. .LINK 
  10.     http://www.pshscripts.blogspot.com 
  11. .EXAMPLE 
  12.     Left as an exercise for the reader 
  13. #> 
  14.  
  15. # Display shares at start 
  16. $start = get-wmiobject win32_share | where {$_.name -match "Foo"
  17. if ($start) { 
  18.   "{0} foo shares at start, as follows:" -f $start.count;  
  19.   $start}  
  20. else {"No foo shares"
  21.  
  22. # Create a foo22 share 
  23. "";"Adding Foo22 share" 
  24. $class = [WMICLASS]'win32_share' 
  25. $ret = $class.create("c:\foo", "foo22", 0,$null,"Test Share Creation with WMI"
  26. if ($ret.returnvalue -eq 0){ 
  27. "Foo22 Share created OK"
  28. else
  29. "Share not created, error code: {0}" -f $ret.returnvalue 
  30.  
  31. # Display results 
  32. "";"Foo shares now:" 
  33. get-wmiobject win32_share | where {$_.name -match "foo"
  34. "" 
  35.  
  36. # Delete the foo22 share 
  37. $del = Get-WmiObject win32_share | where {$_.name -eq "foo22"
  38. $ret = $del.delete() 
  39. if ($ret.returnvalue -eq 0){ 
  40. "share deleted OK"
  41. else
  42. "Share not deleted, error code: {0}" -f $ret.returnvalue 
  43.  
  44. # Display final results 
  45. "";"Foo at the end:" 
  46. $finish = get-wmiobject win32_share | where {$_.name -match "foo"
  47. if ($finish) { 
  48.   "{0} foo shares at the end, as folllows:" -f $start.count;  
  49.   $start}  
  50. else {"No foo shares at the end:"
  51. "" 

This sample, after the now obligatory Advanced Function help stuff, obtains and displays any shares on the local system that contain the string “foo”. Then, in line 24 the scripts gets the Win32_Share class, and in line 25 used the create static method to create a new share (Foo22). In line 39, the script deletes the newly added share, and finally prints out the remaining shares matching “foo”.

In summary, the [WMICLASS] gives you access to the static methods or members exposed by a WMI class.

0 comments: