DCSIMG
Invoking WMI methods in PowerShell - Shay Levy

Shay Levy

If you repeat it, PowerShell it!

Invoking WMI methods in PowerShell

In PowerShell V1 if we wanted to invoke a method, the Win32_Volume WMI Format method in the following example, we used a syntax like:

PS > $vol = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='R:'"
PS > $vol.Format(...)

Note: The Win32_Volume class exists on Windows Server 2003 and above, on Windows XP this class is not available.

 

To determine the values we need to pass to the Format method we pipe the volume object to the Get-Member cmdlet and look at the method definition:

PS > $vol | Get-Member Format -MemberType Method | Format-List Definition

Definition : System.Management.ManagementBaseObject Format(System.String FileSystem, System.Boolean QuickFormat, System.UInt32 ClusterSize, System.String Label, System.Boolean EnableCompression, System.UInt32 Version)

 

We can see that the Format method expects six values: FileSystem, QuickFormat, ClusterSize, Label, EnableCompression and Version. Let's say we want the format the drive as NTFS, enable quick format, the Cluster disk size will be 4096, set the label to "New Volume", disable disk compression and lastly we pass a NULL value to the Version parameter (this will ignore the value of the parameter). When the method is executed the volume is formatted based on the values we supplied.

PS > $vol.Format('NTFS',$true,4096,'New Volume',$false,$null)

__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0

We get a ReturnValue of 0 meaning that the command completed successfully.

 

In PowerShell V2 we have a new way to invoke methods with the Invoke-WmiMethod cmdlet. Invoke-WmiMethod enables us to call WMI methods in a pipeline.

PS > Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='R:'" | `
Invoke-WmiMethod -Name Format -ArgumentList 'NTFS',$true,4096,'New Volume',$false,$null

Nice, the syntax look much cleaner! We feed the name of the method we want to invoke to the Name parameter and supply the same list of arguments we used above (delimited by a comma) to the ArgumentList parameter. Alas, if we execute that command it will fail:

Invoke-WmiMethod : Input string was not in a correct format.

Ouch! What was that? Let's take a look at the help for the ArgumentList parameter:

PS > Get-Help Invoke-WmiMethod -Parameter ArgumentList

-ArgumentList <[Object[]]>
Specifies the parameters to pass to the called method. The value of this parameter must be an array of objects and they must appear in the order required by the called method.
...

 

The problem is the underlying WMI method expects to get the values we pass in a specific order and somehow the order we used doesn't satisfies the method, as if we passed a Boolean value to a parameter that expects a String. We can determine the order of values with the following command:

PS >  ([wmiclass]'Win32_Volume').GetMethodParameters('Format')

__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 6
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ClusterSize : 0
EnableCompression : False
FileSystem : NTFS
Label :
QuickFormat : False
Version : 0

 

Again, we need to send six values to the method but take a closer look at the order of the properties (bold). The order is different than the one we used in the V1 example. Lets re-arrange the values and try again:

PS > Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='R:'" | `
Invoke-WmiMethod -Name Format -ArgumentList 4096,$false,'NTFS','New Volume',$true,$null



Invoke-WmiMethod : Unable to cast object of type 'System.Management.Automation.PSObject'
to type 'System.IConvertible'.


Now we get another error, different than the first one. There's a casting problem, according to the help of the ArgumentList parameter the value of the parameter must be an array of objects, so lets try to explicitly cast the values to an array (i.e with the Array '@()' notation):
PS > Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='R:'" | `
Invoke-WmiMethod -Name Format -ArgumentList @(4096,$false,'NTFS','New Volume',$true,$null)


__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0

 

We get a ReturnValue of 0 and we know the formatting process was successful. The Format method is just an example and you can use the parameters discovery process outlined above for any WMI instance methods. I filed a connect bug so you might want to add your vote if you want the Invoke-WmiMethod to be fixed.

https://connect.microsoft.com/PowerShell/feedback/details/624263/invoking-wmi-methods-with-invoke-wmimethod

 

Now, if you decide to test the Format method make sure you use it on a test drive. For this post I created a new Virtual Hard Disk (VHD) on my Windows 7 machine and gave it the drive letter 'R' (Right Click the Disk Management node in the Computer Management MMC and then click the 'Create VHD' menu item).

Comments

No Comments

Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: