Hey, Scripting Guy! Can Windows PowerShell Call WMI Methods?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have seen a number of methods listed for WMI classes on MSDN, but when I try to use them in Windows PowerShell, they do not work. I am wondering what the secret is to making these things actually do something. I assume they are not really broken because I have VBScripts that I downloaded from the Script Center Script Repository that work just fine. So it must be a Windows PowerShell issue. Can Windows PowerShell call WMI methods?

— DS

Hey, Scripting Guy! AnswerHello DS,

Microsoft Scripting Guy Ed Wilson here. I am feeling much better now that I have had a sufficient amount of sleep. The jet lag from my trip to Seattle, Washington, in the United States for the Microsoft TechReady conference is over. As one late twentieth century American philosopher once stated, “I feel good.” I have my little blue tea pot with some nice Earl Grey tea and an ANZAC biscuit. My friend Brett in Sydney, Australia, sent a couple of packages of ANZAC biscuits and Tim Tams to me while I was in Seattle by way of another friend (Hemant) who was also attending the TechReady conference, which was good because I had run out of both. Because I now have a stash of ANZAC biscuits, I am sipping tea, munching an ANZAC biscuit, and listening to James Brown on my Zune. Yes, it is good to be home.

DS, short answer: Yes, Windows PowerShell can call WMI methods. As an example, on Windows Server 2003 and later there is a really cool WMI class named Win32_Volume. The reason I love this WMI class is because of the methods. The properties are easy to obtain by using the Get-WmiObject cmdlet. (One thing that is cool is the system property __Property_Count. This tells us there are 44 properties on the Win32_Volume WMI class.) This is seen here:

PS C:> Get-WmiObject -Class win32_volume


__GENUS                      : 2
__CLASS                      : Win32_Volume
__SUPERCLASS                 : CIM_StorageVolume
__DYNASTY                    : CIM_ManagedSystemElement
__RELPATH                    : Win32_Volume.DeviceID=”\\?\Volume{a281f0f1-45
                               07-11dc-be35-806e6f6e6963}\”
__PROPERTY_COUNT             : 44
__DERIVATION                 : {CIM_StorageVolume, CIM_StorageExtent, CIM_Logic
                               alDevice, CIM_LogicalElement…}
__SERVER                     : VISTA
__NAMESPACE                  : rootcimv2
__PATH                       : \VISTArootcimv2:Win32_Volume.DeviceID=”\\?
                               Volume{a281f0f1-4507-11dc-be35-806e6f6e6963}\”
Access                       :
Automount                    : True
Availability                 :
BlockSize                    : 4096
BootVolume                   : True
Capacity                     : 68716326912
Caption                      : C:
Compressed                   : False
ConfigManagerErrorCode       :
ConfigManagerUserConfig      :
CreationClassName            :
Description                  :
DeviceID                     : \?Volume{a281f0f1-4507-11dc-be35-806e6f6e6963}
                              
DirtyBitSet                  : False
DriveLetter                  : C:
DriveType                    : 3
ErrorCleared                 :
ErrorDescription             :
ErrorMethodology             :
FileSystem                   : NTFS
FreeSpace                    : 51106398208
IndexingEnabled              : False
InstallDate                  :
Label                        :
LastErrorCode                :
MaximumFileNameLength        : 255
Name                         : C:
NumberOfBlocks               :
PageFilePresent              : True
PNPDeviceID                  :
PowerManagementCapabilities  :
PowerManagementSupported     :
Purpose                      :
QuotasEnabled                : False
QuotasIncomplete             : False
QuotasRebuilding             : False
SerialNumber                 : 4241210807
Status                       :
StatusInfo                   :
SupportsDiskQuotas           : True
SupportsFileBasedCompression : True
SystemCreationClassName      :
SystemName                   : VISTA
SystemVolume                 : True

__GENUS                      : 2
__CLASS                      : Win32_Volume
__SUPERCLASS                 : CIM_StorageVolume
__DYNASTY                    : CIM_ManagedSystemElement
__RELPATH                    : Win32_Volume.DeviceID=”\\?\Volume{a281f0f4-45
                               07-11dc-be35-806e6f6e6963}\”
__PROPERTY_COUNT             : 44
__DERIVATION                 : {CIM_StorageVolume, CIM_StorageExtent, CIM_Logic
                               alDevice, CIM_LogicalElement…}
__SERVER                     : VISTA
__NAMESPACE                  : rootcimv2
__PATH                       : \VISTArootcimv2:Win32_Volume.DeviceID=”\\?
                               Volume{a281f0f4-4507-11dc-be35-806e6f6e6963}\”
Access                       :
Automount                    : True
Availability                 :
BlockSize                    :
BootVolume                   :
Capacity                     :
Caption                      : D:
Compressed                   :
ConfigManagerErrorCode       :
ConfigManagerUserConfig      :
CreationClassName            :
Description                  :
DeviceID                     : \?Volume{a281f0f4-4507-11dc-be35-806e6f6e6963}
                              
DirtyBitSet                  :
DriveLetter                  : D:
DriveType                    : 5
ErrorCleared                 :
ErrorDescription             :
ErrorMethodology             :
FileSystem                   :
FreeSpace                    :
IndexingEnabled              :
InstallDate                  :
Label                        :
LastErrorCode                :
MaximumFileNameLength        :
Name                         : D:
NumberOfBlocks               :
PageFilePresent              :
PNPDeviceID                  :
PowerManagementCapabilities  :
PowerManagementSupported     :
Purpose                      :
QuotasEnabled                :
QuotasIncomplete             :
QuotasRebuilding             :
SerialNumber                 :
Status                       :
StatusInfo                   :
SupportsDiskQuotas           :
SupportsFileBasedCompression :
SystemCreationClassName      :
SystemName                   : VISTA
SystemVolume                 :

One thing you will notice is that not all properties return data. One day, DS, I will show you a really cool way to take care of the missing property value problem (the technique is something I came up with while I was writing the 200 scripts for the Windows 7 Resource Kit), but that is a subject for a future Hey, Scripting Guy! article. The thing that is important to notice here is that there are two instances of Win32_Volumes returned in response to our query. If I were to run this script on my other desktop, I would have six instances of the Win32_Volume class returned. Because there are multiple instances of the Win32_Volume WMI class returned by the Get-WmiObject cmdlet, it means that you cannot directly access the methods. This is in spite of the fact that the Get-Member cmdlet clearly displays them as seen here:
 

PS C:> Get-WmiObject -Class win32_volume | Get-Member -MemberType method


   TypeName: System.Management.ManagementObject#rootcimv2Win32_Volume

Name           MemberType Definition
—-           ———- ———-
AddMountPoint  Method     System.Management.ManagementBaseObject AddMountPoi…
Chkdsk         Method     System.Management.ManagementBaseObject Chkdsk(Syst…
Defrag         Method     System.Management.ManagementBaseObject Defrag(Syst…
DefragAnalysis Method     System.Management.ManagementBaseObject DefragAnaly…
Dismount       Method     System.Management.ManagementBaseObject Dismount(Sy…
Format         Method     System.Management.ManagementBaseObject Format(Syst…
Mount          Method     System.Management.ManagementBaseObject Mount()
Reset          Method     System.Management.ManagementBaseObject Reset()
SetPowerState  Method     System.Management.ManagementBaseObject SetPowerSta…

If you attempt to directly access any of the methods, an error will be generated. This is because WMI does not know which volume you wish to work with. This is seen here:
 

PS C:> (Get-WmiObject -Class win32_volume).defragAnalysis()
Method invocation failed because [System.Object[]] doesn’t contain a method nam
ed ‘defragAnalysis’.
At line:1 char:51
+ (Get-WmiObject -Class win32_volume).defragAnalysis <<<< ()
    + CategoryInfo          : InvalidOperation: (defragAnalysis:String) [], Ru
   ntimeException
    + FullyQualifiedErrorId : MethodNotFound

PS C:> $wmi = Get-WmiObject -Class win32_volume
PS C:> $wmi.DefragAnalysis()
Method invocation failed because [System.Object[]] doesn’t contain a method nam
ed ‘DefragAnalysis’.
At line:1 char:20
+ $wmi.DefragAnalysis <<<< ()
    + CategoryInfo          : InvalidOperation: (DefragAnalysis:String) [], Ru
   ntimeException
    + FullyQualifiedErrorId : MethodNotFound

To work with the method, you will need to obtain a single instance of the class. There are a couple of ways to do this. You do not have to only have a single instance of the class, but you must be working with a single instance at a time. The easiest way to call the method is to use the Foreach-Object cmdlet to work through the collection of Win32_Volumes. To do this, you use the Get-WmiObject cmdlet to query for all instances of the Win32_Volume, and you use the pipeline to pass the objects to the Foreach-Object cmdlet. Inside the script block for the Foreach-Object cmdlet, you use the $_ automatic variable to refer to the current object on the pipeline. This allows you to call the DefragAnalysis method. This technique is seen here:
 

PS C:> Get-WmiObject -Class win32_volume | Foreach-Object { $_.DefragAnalysis()
 }


__GENUS           : 2
__CLASS           : __PARAMETERS
__SUPERCLASS      :
__DYNASTY         : __PARAMETERS
__RELPATH         :
__PROPERTY_COUNT  : 3
__DERIVATION      : {}
__SERVER          :
__NAMESPACE       :
__PATH            :
DefragAnalysis    : System.Management.ManagementBaseObject
DefragRecommended : False
ReturnValue       : 0

__GENUS           : 2
__CLASS           : __PARAMETERS
__SUPERCLASS      :
__DYNASTY         : __PARAMETERS
__RELPATH         :
__PROPERTY_COUNT  : 3
__DERIVATION      : {}
__SERVER