PowerShell WMI Techniques

Introduction to PowerShell’s WMI Techniques

One of the most useful jobs for PowerShell is to create a bank of WMI based scripts.  Furthermore, scripting WMI with PowerShell is much easier and more efficient than WMI with VBScript.

Topics for PowerShell WMI Techniques


WMI Perspective

To appreciate the beauty of a crystal, you should examine the facets from different angles.  The same applies to the diamond that is WMI; I recommend that to gain perspective we investigate WMI from these five angles.

  1. Imagine WMI as a database, which keeps information about a computer’s components such as the: BIOS, services and network settings.
  2. Regard WMI as a method for collecting data about a machine’s hardware and software.
  3. View WMI as a pipe, which magically connects to the core of any Microsoft operating system (post 2000).
  4. Think of WMI as a having its own PowerShell dialect, for example the WQL select clause.
  5. Treat WMI as a microscope, and use it to probe the operating system’s objects and their properties.

Whenever I think about WMI for any length of time, it hits me: the operating system must know everything that’s going on!  Therefore, provided the PowerShell script has sufficient rights, it can use WMI and tap into that vast fountain of operating system knowledge.  The Windows operating system must know ‘stuff’ such as how much memory each process is using, how much free space there is on each partition, which devices are on which Bus.  It is even possible to manipulate or ‘set’ values on some of these properties and thus achieve configuration via scripts rather than GUIs.

Guy Recommends: Free WMI Monitor for PowerShellSolarwinds Free WMI Monitor for PowerShell

Windows Management Instrumentation (WMI) is one of the hidden treasures of Microsoft’s operating systems.  Fortunately, SolarWinds have created a Free WMI Monitor so that you can discover these gems of performance information, and thus improve your PowerShell scripts.

Take the guess work out of which WMI counters to use when scripting the operating system, Active Directory, or Exchange Server. Give this WMI monitor a try – it’s free.

Download your free copy of WMI Monitor

Get-WmiObject – Getting Started

Get-WmiObject is the key command.  As we will see, it unlocks zillions of classes such as Win32_Computer, here is the simple example that got me interested in PowerShell WMI:

# PowerShell GetWmiObject Example
Get-WmiObject Win32_Computersystem

The result was:

Domain : cp.mosel
Manufacturer : VIAK8T
PrimaryOwnerName : Guy
TotalPhysicalMemory : 2146910208

I was curious to discover what other WMI Objects were available for scripting; then I remembered the -List switch from another PowerShell command (Get-Eventlog -List).  Thus I tried:

# PowerShell Get-WmiObject example to list classes
Get-WmiObject -List

Next, I redirected the output from the screen to a file by appending ‘Out-File’:
out-File WmiObject.txt.  To make:

# PowerShell Get-WmiObject example
Get-WmiObject -List | Out-File WmiObject.txt

See a Review of SolarWinds WMI Monitor »

Researching WMI Classes with ‘Where-Object’

My next problem was the list was too long, therefore I added a ‘Where’ filter

Get-WmiObject -List | Where-Object {$_.name -Match "Win32"}

And even better:

Get-WmiObject -List |Where-Object {$_.name -Match "Win32"} `
 | Out-File D:\wmi\win.txt

Learning Points

Note 1:  The tiny backtick (`) tells PowerShell that the command continues on the next line.

Note 2:  On other pages I use plain ‘Where’, or even ‘?’ instead of the full ‘Where-Object’.

Note 3: I expect you have guessed that PowerShell commands are case insensitive.  At present I am not sure which is best, WmiObject, wmiObject or WmiObject – they all produce the same results.  Another minor point, since the verb ‘get’ is the default, you can shorten the command to:
WmiObject Win32_computersystem.  Or if you like aliases: gwmi Win32_computersystem.

Guy Recommends:  A Free Trial of the Network Performance Monitor (NPM)Review of Orion NPM v11.5 v11.5

SolarWinds’ Network Performance Monitor will help you discover what’s happening on your network.  This utility will also guide you through troubleshooting; the dashboard will indicate whether the root cause is a broken link, faulty equipment or resource overload.

What I like best is the way NPM suggests solutions to network problems.  Its also has the ability to monitor the health of individual VMware virtual machines.  If you are interested in troubleshooting, and creating network maps, then I recommend that you try NPM now.

Download a free trial of Solarwinds’ Network Performance Monitor

WmiObject Get-Member

Wouldn’t it be useful to get a list of all the properties on a PowerShell object?  The answer is Get-Member.  Here is an example of applying the Get-Member command to examine the Win32_Logical Disk:

Example 1

# List Get-WmiObject properties
Get-WmiObject Win32_LogicalDisk | Get-Member

Sample Output (Heavily truncated)

Get-WmiObject Win32_LogicalDisk | Get-Member

Example 2

Here is another example, this time PowerShell interrogates the LogicalDisk:

TypeName: System.Management.ManagementObject#root\cimv2\Win32_LogicalDisk
Name MemberType Definition
—– ———– ———-
add_Disposed Method System.Void add_Disposed(EventHandler value)
Clone Method System.Object Clone()
Access Property System.UInt16 Access {get;}
Availability Property System.UInt16 Availability {get;}
BlockSize Property System.UInt64 BlockSize {get;}
Caption Property System.String Caption {get;}
Compressed Property System.Boolean Compressed {get;}

WmiObject – Help with Parameters

When I am in ‘let us get started’ mode, I gloss over the optional PowerShell commands.  However, when we need to troubleshoot, then the secret of success is knowledge of a command’s parameters.  To reveal the full list of parameter, let’s call for help:

# PowerShell Get-WmiObject see more parameters
Get-Help Get-Wmiobject -full

Five useful Wmiobject Parameters



When you employ Get-Wmiobject the first thing you want to specify is the class of the object, for example: Win32_LogicalDisk.  If this class name follows directly after Get-Wmiobject there is no need to explicitly use the -class parameter.  PowerShell assumes from the first position that the word defines the type of class you wish to script.

Get-Wmiobject -class Win32_WmiSetting

Abbreviated version of the same cmdlet

Get-Wmiobject Win32_WmiSetting


The reason that the -namespace parameter is optional because Wmiobject has a default value of: root\cimv2.  Thus the time to include this parameter is when you wish to use a different namespace, such as: root\directory\ldap.

Get-WmiObject -namespace "root\cimv2" -List

A different namespace: "root\directory\ldap"

Get-WmiObject -namespace "root\directory\ldap" -List

The full syntax to specify the class and the namespace:

Get-Wmiobject -class Win32_WmiSetting -namespace "root\cimv2"

Note 4:  Interestingly, when you explicitly define the namespace, the command displays more properties, than if you omit the parameter and rely on the default.

Guy Recommends:  SolarWinds’ Free Bulk Import ToolFree Download Solarwinds Bulk Import Tool

Import users from a spreadsheet.  Just provide a list of the users with their fields in the top row, and save as .csv file.  Then launch this FREE utility and match your fields with AD’s attributes, click and import the users.

Optionally, you can provide the name of the OU where the new accounts will be born. Download your FREE bulk import tool.

If you need more comprehensive application analysis software,
Download a free trial of SAM (Server & Application Monitor)


As expected, when you use Get-Wmiobject PowerShell defaults to the current machine; unlike VBScript, you don’t have to add "."  However, if you want to run the script against another machine you need to add the -computerName parameter.  Incidentally, the target machine must have WMI, but does not need PowerShell.  As all Microsoft Computers after Windows 2000 have WMI, there should be no problem; your only real concern could be firewalls.  Knowledge of the -computerName parameter helps when you want a script which loops through multiple hostnames, or IP addresses.

Get-Wmiobject -class Win32_WmiSetting `
-namespace "root\cimv2" -computerName bigserver

Note 5:  If you would like to run my cmdlet on your network, then please amend ‘bigserver’ to the name of a real machine on your subnet.

Note 6: To cope with word-wrap I added the tiny backtick ` command.  This tells PowerShell that there is one command but it is split over two lines.

Note 7:  As far as I can see, the shorter -computer works just as well as the longer -computerName.  In fact, this is an example of PowerShell’s intelligence, as soon as the word that you are typing becomes unique, then PowerShell automatically fills in the missing letters.  To see what I mean try -comput, or even -comp.

Note 8:  See more about the [WMI] Type syntax.


To illustrate the -filter parameter, let us set the scene:  you wish to interrogate the logical disk, but you only want information about the ‘c:’ drive.  Incidentally, -filter is much easier than comparable constructions in VBScript.

Get-WmiObject Win32_LogicalDisk -filter "DeviceID = ‘c:’ "

Note 9:  Pay close attention to the quotes.  One set of double quotes surrounding "Device ID = ".  And one set of single quotes around the disk drive ‘c:’.

Note 10:  PowerShell’s usual comparison operators employ -eq.  However, here -filter requires the equals sign.

Note 11:  To concentrate on the main feature -filter, I omitted the optional parameters that we covered previously.


In this example, imagine that we need information about the hard disk, but we don’t want the results cluttered with data about floppy drives, CD or DVD drives.  If you are familiar with any dialect of SQL you may recognise the select statement below:

Get-WmiObject -query "select * from Win32_LogicalDisk where DriveType =’3′ "

Note 12: As with -filter, you need to be careful with syntax of the -query parameter.  Observe the quotes, and how I have separated the single quote from the double quote with a space: = ‘3’ ".  In fact, as 3 is a numeric value, we could remove these single quotes and simplify the expression to: where DriveType = 3.

Guy Recommends: SolarWinds Free Network Bandwidth MonitorFree Real-Time Bandwidth Monitor

This freeware monitor is great for checking whether your network’s load-balancing is performing as expected, for example, are two interfaces are getting about equal traffic?

It’s easy to install and straightforward to configure. You will soon be running tests to see how much network bandwidth your applications consume.

The GUI has a lovely balance between immediate network traffic data in the middle, combined with buttons to seek related data and configuration settings. Give this monitor a try, it’s free! 

Download your free network bandwidth monitor

If you need more comprehensive network analysis software:
Download a free trial of NPM (Network Performance Monitor)

WmiObject $variables

Let us kill two birds with one stone.  Firstly, I want to introduce variables and secondly, I want to filter the properties for a WMI Object.  This is the idea, let us set a variable called $disk equal to Get-WmiObject Win32LogicalDisk.  Now we can call individual properties, for example $disk.Name, or $disk.Size.

There is one additional script structure we must master, the foreach construction.  Since there is more than one drive we need the foreach loop below.  Observe how this construction requires a placeholder ($drive in $disk).

Simple Example

$dsk= Get-WmiObject Win32_LogicalDisk
foreach ( $drive in $dsk ) { "Drive = " + $drive.Name}

Note 13: In PowerShell v 2.0 $Disk appears to be a built-in variable that is why I changed to $dsk

Extra Maths Example

# Cmdlet to display the size of disk partitions
$dsk= Get-WmiObject Win32_LogicalDisk
"Drive Letter Size GB"
foreach ( $drive in $dsk ) { "Drive = " + $drive.Name + `
" Size = " + [int]($drive.Size/1073741824)}

Note 14: PowerShell 2.0 has built-in math functions to make the calculation easier.  Try substituting:
($drive.Size/1Gb), or ($drive.Size/1Mb) if you prefer megabytes.

Learning Points

Results (Your values for Size will be different!)

Drive Letter Size GB
Drive = A: Size = 0
Drive = B: Size = 0
Drive = C: Size = 49
Drive = D: Size = 29
Drive = E: Size = 85

To recap, we begin with the variable $disk.  We set its value = Get-WmiObject Win32_LogicalDisk.  We want to display the name $drive.Name and the size $drive.Size.  Because the raw disk size is in bytes, we best convert to gigaabytes (GB), thus we need to divide by 1024 x 1024 x 1024 (1073741824).  [int] displays the number as an integer.

With the brackets it is always worth paying attention to detail.  PowerShell is particular about the style of bracket, for example {Int} or even (int) draw an ‘unexpected token’ error message.  Equally, the foreach construction needs the simple elliptical brackets (), while the properties are encased in curly {} brackets.

Get-WmiObject Alias Gwmi

Instead of Get-WmiObject you may see gwmi, this is one of the most commonly used PowerShell aliases.  This is a technique for checking to see if a PowerShell cmdlet has one or more aliases.

# Get-WmiObject Alias Gwmi
Get-Alias -definition Get-WmiObject

Summary of PowerShell Get-WmiObject

Get-WmiObject is a good bellwether for PowerShell. Contrast the ease with which PowerShell displays WMI objects, with the struggle which VBScript achieves the same result. 

Skills that you develop through experimenting with PowerShell and WMI will help you manage your Exchange 2007 server.  With practice, you will also be able to adapt these techniques to Active Directory and Windows Server 2008.  My point is that while PowerShell is clearly has a future, you can get started here and now by creating WMI cmdlets.

If you like this page then please share it with your friends


See More Microsoft PowerShell WMI Examples:

Home   • PowerShell Get-WmiObject   • Windows PowerShell   • PowerShell 3.0 Network

Win32_pingstatus   • WMI Win32_NetworkAdapter   • Win32_NetworkAdapterConfig

Disable NIC   • PowerShell -Filter  • PowerShell -Query   • PowerShell Select   • Free WMI Monitor

Please email me if you have any example scripts. Also please report any factual mistakes, grammatical errors or broken links, I will be happy to correct the fault.