Evaluate Weigh the pros and cons of technologies, products and projects you are considering.

Working with WMI providers to PowerShell

Microsoft's new shell language, Windows PowerShell, works with data from .NET 2.0. But .NET doesn't always contain the objects you need. In this Scripting School column, Christa Anderson explains how to use PowerShell with Windows Management Instrumentation providers.

Last month I discussed how Windows PowerShell was a consistent shell interface to .NET. But that's not the whole story.

At this point, .NET does not describe a computer's every hardware and software component. Where it falls short, you'll need to call on one of its providers, which describe objects not yet described in .NET 2.0.

A provider is a collection of interfaces to managed objects, which can be consumed by the programming/scripting language. Conceptually, a provider is like a marionette. The doll's arms and legs are managed objects while your hand is the scripting language. The strings and sticks that connect the doll to your hand allow you to manipulate them, albeit indirectly.

Key points on working with Windows Management Instrumentation providers

  • PowerShell works with data not only from .NET 2.0, but also external providers such as WMI when .NET doesn't contain the objects you need.
  • You can use PowerShell to return information about WMI classes. Once you have the classes, you can return the objects within that class.
  • To manipulate all instances of an object, use the ForEach-Object cmdlet.
  • PowerShell uses standard operators for performing mathematical operations.
  • If a property is read/only and you want to edit it, create a new object to represent it.

You can actually write your own providers if you like, but let's start with an existing provider. To illustrate this, let's perform a disk inventory via the Windows Management Instrumentation (WMI) interface, because disks are not represented in .NET 2.0. As you'll see, although you can access WMI via VBScript, it's a lot easier using Windows PowerShell.

Windows Management Instrumentation (WMI) is an object-oriented way of describing the hardware and software in your computer. Objects are organized into classes of like objects (such as network cards, OSes, computers or logical disk drives). As with the objects discussed in previous Scripting School columns, they all have properties and, sometimes, methods.

Properties describe an object; methods are what you can do to that object (outside of editing its properties, which often counts as manipulating it). WMI works on a local computer as well as remotely. But you cannot access a remote computer unless it has WMI installed and you have administrative privileges on it.

Performing a disk inventory with WMI

Let's start by collecting disk information about all the local drives. I'll start by typing:


Windows PowerShell will prompt me for the class of object I want. Hmm, which one do I want? There are hundreds of classes. But with PowerShell I can see the classes on my computer via the –list parameter (Get-Wmiobject-list). (It's still a lot to go through, but it is complete.) After viewing the classes, I can make a decent guess that Win32_LogicalDisk includes information about disks on the computer, and enter this class name at the prompt:

Class: Win32_LogicalDisk

Now I get back the following:

DeviceID : C:
DriveType : 3
ProviderName :
FreeSpace : 15139065856
Size : 80015491072
VolumeName :

DeviceID : D:
DriveType : 5
ProviderName :
FreeSpace : 0
Size : 0
VolumeName : Audio CD

DeviceID : Z:
DriveType : 4
ProviderName : VisionthingFirefox downloads
FreeSpace : 15139065856
Size : 80015491072
VolumeName :

Get-wmiobject tries to parse arguments not identified as classes as classes. I will get the same results if I type the entire command on one line. Therefore, the following two commands are equivalent:

get-wmiobject win32_logicaldisk

get-wmiobject -class win32_logicaldisk

Now I have basic information about the drives on my computer. I've listed one fixed disk (type 3), one DVD/CD drive (type 4) and one network drive (type 5). I know these drive types because I looked them up.

Filtering data with WMI

But I don't want to show every single disk on my computer. It doesn't help me to know there's no free space on a CD-R; I want to return the fixed drives. With Windows PowerShell, this is simple. Just filter on the DriveType property.

get-wmiobject -class Win32_LogicalDisk -filter "DriveType=3"

This command will return only the fixed drives in my system.

Formatting the value with WMI

One failing of WMI is that it returns the volume size and free space in bytes. Since I'm working on a laptop with a 75GB drive, listing the size in bytes makes the value hard to read. To convert to gigabytes, I'll need to get the value of the FreeSpace property for each fixed drive, then divide the values by 1024 three times each, on one line, like this:

Get-WmiObject -Class Win32_LogicalDisk –filter "DriveType=3" | ForEach-Object -Process {($_.FreeSpace)/1024/1024/1024}

ForEach-Object –Process processes the data enclosed in brackets. This operation returns the correct value of gigabytes remaining on my fixed disk.

But wait—I've lost my label! That's because FreeSpace is a read-only property; you can't convert it to show its value in gigabytes. This is annoying. to pipe this output to a file and identify what I'm looking at, I'll need to create a new object that is read/write.

To do this, I'll get the results of FreeSpace as I already did for each fixed drive in the system, then pipe that output to a new cmdlet called populating it with the properties I need to identify the data I've collected.

Get-WmiObject -Class Win32_LogicalDisk -filter "DriveType=3" | Select-Object -Property Name,FreeSpace

Once you do this, you're ready to operate on the value of FreeSpace to convert it to gigabytes. The whole command looks like this:

Get-WmiObject -Class Win32_LogicalDisk -filter "DriveType=3" | Select-Object -Property Name,FreeSpace | ForEach-Object -Process {$_.FreeSpace = ($_.FreeSpace)/1024/1024/1024; $_}

and returns this:

Name FreeSpace
---- ---------
C: 14.0946578979492

To review, the previous command does the following:

  • Gets the WMI objects in the Win32_Logical Disk class;
  • Filter themso that only fixed drives are returned;
  • Sends the values of the Name and FreeSpace properties to a new object; and
  • Processes the value of FreeSpace so that it displays in gigabytes.

Read all of Christa Anderson's scripting columns on SearchWinComputing.com.

Christa Anderson
A Terminal Services MVP, Christa Anderson is the strategic technology manager for visionapp She formerly was program manager for the Microsoft Terminal Services team. She is an internationally known authority on scripting, the author of Windows Terminal Services, The Definitive Guide to MetaFrame XP, and co-author of the book Mastering Windows 2003 Server. If you have a scripting question for Christa, please email her at [email protected] She often uses these emails as fodder for her scripting columns.

Dig Deeper on Windows Server troubleshooting