How to use WMI with Windows PowerShell scripts
With PowerShell, admins can harness the power of WMI to find all sorts of system and network information. The best part? It’s probably a lot easier than you think.
Windows Management Instrumentation (WMI) is one of those tools that can change your proverbial life. But while it’s been around since the early 90s, the adoption of WMI has been slowed due to its complicated nature. Windows PowerShell has torn down this wall by making WMI much easier to use in a way that’s changing the face of IT.
Before we dive into exactly how PowerShell simplifies WMI, let’s take a look at what exactly WMI is. In the simplest terms, you can think of WMI as a library filled with resources that provide all sorts of data in a consistent and reliable format.
Wikipedia explains the purpose of WMI as a way to “define a non-proprietary set of environment-independent specifications [that] allow management information to be shared between management applications.” That’s a pretty abstract explanation, and while WMI may have started as an attempt for “environment-independence”, things have now changed, starting with what’s considered these days to be WMI. When you hear about WMI today, it’s generally used in the context of Microsoft’s implementation of WMI via build-in providers. That’s what we’ll focus on here.
WMI can be broke down into three basic components:
- Provider -- grants access to managed objects and provides availability to the WMI API
- Classes -- a WMI representation of objects with properties and methods
- Namespace -- a logical grouping of classes
So how can PowerShell help make WMI easier to access?
First, let’s look at the tools PowerShell offers for WMI. There are basically five PowerShell cmdlets that make working with WMI a breeze. I will list all of them here, but I’m really only going to focus on one of them (Get-WMIObject):
-
Get-WmiObject -- returns object(s) based on the namespace and class provided
-
Invoke-WmiMethod -- calls WMI methods (commonly used to execute static methods)
-
Register-WmiEvent -- used to subscribe to WMI events
-
Remove-WmiObject -- deletes an instance of an existing WMI class (to be clear, it doesn’t delete the actual class itself, but the instance of the class you have in memory)
-
Set-WmiInstance -- creates or updates an instance of an existing WMI class (use this one with caution as it actually writes to the WMI repository)
Now let’s tackle the biggest problem with WMI, which is figuring out exactly what’s there and what data it provides. There are several ways to get this information, but let’s start with the built-in option.
You can list providers by doing the following:
$Root = "\\.\ROOT:__namespace"
$WMIProv = New-Object System.Management.ManagementClass
($Root)
$WMIProv.GetInstances() | Select Name
(Granted, this is a little more complicated than the rest of the tasks. Fortunately, you shouldn’t have to do this often.)
Here is how you list the classes provided by a specific namespace (default is Root\CIM2, which has all the Microsoft Win32 classes):
# On local machine
Get-WmiObject –Namespace Root\SecurityCenter –List
# On Remote machine
Get-WmiObject –Namespace Root\SecurityCenter –List
–Computer core
# To filter you can use wildcards
Get-WmiObject –Namespace Root\SecurityCenter –List
*firewall*
# To list the classes for HyperV on remote server
Get-WmiObject –Namespace Root\Virtualization –List
–Computer core
(This is the hard way, but you can cheat by using free tools like WMI Explorer or Microsoft’s PowerShell Scriptomatic.)
Now it’s time to get down and dirty with Get-WMIObject, which is by far the most useful of the five cmdlets. With this in your toolbox you are only one line away from almost any piece of data (Microsoft OS-related) you can think of. There are over 600 Win32 classes that expose things like CPU, memory, disk, processes, network, BIOS, USB and more. Excited? Just wait until you see how simple it is.
To get operating system info:
Get-WmiObject–class win32_OperatingSystem
To get computer system info:
Get-WmiObject–class win32_ComputerSystem
To get disk info:
Get-WmiObject–class Win32_LogicalDisk
To get network info:
Get-WmiObject –class Win32_NetworkAdapterConfiguration
Just give it a try – it really is that easy.
Let’s finish up by looking at an example script using WMI to get IP information. The useful script below replaces ipconfig and its usually awful output.
function Get-IP
{
[Cmdletbinding()]
Param(
[alias('dnsHostName')]
[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=
$true) [string]$ComputerName = $Env:COMPUTERNAME
)
process
{
$NICs = Get-WmiObject
Win32_NetworkAdapterConfiguration -Filter
"IPEnabled='$True'" -ComputerName $ComputerName
foreach ($Nic in $NICs)
{
$myobj = @{
Name = $Nic.Description
MacAddress = $Nic.MACAddress
IP4 = $Nic.IPAddress | where{$_
-match
"\d+\.\d+\.\d+\.\d+"}
IP6 = $Nic.IPAddress | where{$_
-match "\:\:"}
IP4Subnet = $Nic.IPSubnet | where{$_
-match
"\d+\.\d+\.\d+\.\d+"}
DefaultGWY = $Nic.DefaultIPGateway |
Select -First 1
DNSServer = $Nic.DNSServerSearchOrder
WINSPrimary = $Nic.WINSPrimaryServer
WINSSecondary = $Nic.WINSSecondaryServer
}
$obj = New-Object PSObject -Property $myobj
$obj.PSTypeNames.Clear()
$obj.PSTypeNames.Add('BSonPosh.IPInfo')
$obj
}
}
}
You can find more general information about WMI at the Microsoft website, along with a WMI glossary of terms and Win32 class list.
Miss a column? Check out our Scripting School archive.
You can follow SearchWindowsServer.com on Twitter @WindowsTT.
ABOUT THE AUTHOR
Brandon Shell has been in the IT industry since 1994. He started out as a PC tech and general fix-it guy for numerous companies. In 2007, he joined the PowerShell MVP ranks, and Shell has spent the past several years building his PowerShell knowledge and helping others build theirs.