Over the years I have written a number of articles explaining how to create various types of reports using data that has been obtained through various PowerShell cmdlets. While it is true that PowerShell Get cmdlets can return a wealth of information, you can gain access to far more data if you delve into Windows Management Instrumentation (WMI).
WMI is often thought of as being one of those things that only developers mess with. I get it. The good news, however, is that PowerShell makes it really easy to extract data from WMI. You don’t have to be a developer to get the job done. You don’t even have to know anything about WMI. The techniques that I will be showing you are all done using native PowerShell.
The first thing that you need to know about working with WMI is that WMI objects are divided into classes and properties. You can think of a WMI class as being kind of like a category, and the properties are essentially attributes of that category.
Getting information from the OS
So with that in mind, imagine that we were trying to get information about the Windows operating system. The operating system itself would be the class (actually, it is called Win32_OperatingSystem), and things like BuildNumber, Version, and RegisteredUser would be properties of that class.
One of the things that admins often find intimidating about working with WMI is just the sheer number of objects that are available. There are hundreds of different classes, and many of the classes contain huge numbers of properties.
If you are curious about the classes that exist within Windows, just enter the command below:
This command lists the WMI object classes that exist on the current computer. Incidentally, you can look at a remote system instead by appending the -ComputerName parameter and the name of the remote system that you wish to examine.
As you can see in the figure below, entering the Get-WMIObject -List command displays a list of the available WMI classes, and at least a partial list of the available properties.
So let’s go ahead and do something useful with this information. Let’s suppose that we want to view some detailed information about the operating system, and we want to use the Win32OperatingSystem class to do it. If you want to see some of the available properties for that class, just enter the Get-WMIObject cmdlet, followed by the name of the class. In this case, the command would be Get-WMIObject Win32_OperatingSystem. You can see the command’s output in the figure below.
If you have spent much time working with PowerShell, then you know that very often Get commands only display a subset of the information that is available. This is exactly what is going on here. If you want to see all of the properties that are available within a class, you will need to append either Format-List or Format-Table, followed by an asterisk. The figure below shows that there are many more properties available for the Win32_OperatingSystem class than what is shown by default.
Let’s write a script
So with that in mind, let’s pretend that for whatever reason, we need to write a script that uses WMI to look up the name of the operating system. We could actually do that with one line of code (which you can see in the next screen capture), but let’s make things a bit more interesting. Rather than just looking up the operating system name, let’s map it to a variable so that we can reference it elsewhere in a PowerShell script.
At first, this seems like something really easy to do. We could conceivably use a command like this one:
$OS = Get-WMIObject Win32_OperatingSystem | Select-Object Caption
The problem with using this command is that the $OS variable will end up containing more than just the name of the operating system. It will also store the column header (which consists of the word Caption and a series of dashes). You can see what this looks like in the figure below.
As such, we need a way of isolating the name of the operating system so that the $OS variable will store the operating system name and nothing else.
The command that we will actually need to use is very similar to the one that I just showed you The difference is that rather than using the Select-Object cmdlet, which will always display a column header, we must simply reference the property that we are interested in directly. Here is what the command looks like:
$OS = (Get-WMIObject Win32_OperatingSystem).Caption
What I have done is to enclose the Get_WMIObject cmdlet and the name of the WMI class that I am using in parentheses. Once I have done that, I can just add a period and the name of the property that I want to assign to a variable. You can see how this works in the figure below.
An important skill to know
I would strongly encourage anyone who does a lot of PowerShell scripting to spend some time exploring the various WMI classes. Admittedly, WMI can be a bit overwhelming because of the sheer number of classes and properties that are available. Even so, understanding the basics of how to access WMI from PowerShell will greatly increase what you are able to accomplish with your PowerShell scripts.
One way that you might be able to get around the problem of having too many WMI classes is to do a Web search and see which classes other people find to be the most useful Another thing that you can do is to look up which WMI class contains some specific piece of information that you wish to reference in your script.