PowerShell guide to Get-CimInstance & Get-WmiObject

Brock Bingham candid headshot
Brock Bingham|August 26, 2021
cimwmi
cimwmi

Computers store colossal amounts of data. We're talking registries, files, settings, directories, permissions, general information, ones and zeros, and all sorts of magical nerd stuff. While most users are content just accessing their TPS reports and dank memes, we sysadmin types love getting our Dorito fingers all over every bit of that data. 

But, keep in mind, sysadmins tend to be a reclusive bunch, avoiding, whenever possible, public spaces, awkward conversations, and sunlight in general. So, how can we access all that data while maintaining our high degree of self-isolation? By the power of Greysk — ahem — PowerShell! More specifically, Get-CimInstance and Get-WmiObject!

If you haven't figured it out by now, I don't know what to tell you. PowerShell is taking over. There's not much it can't do these days. Give it a few more years, and we'll have robots stomping around saying, "Get-ChildItem -Name 'John Connor'." 

However, before we welcome our robot overlords, we can employ PowerShell to help us remotely collect and utilize the data stored on our computers.

CIMWMI

Get-CimInstance vs. Get-WmiObject

You may be wondering what the difference is between Get-CimInstance and Get-WmiObject, and the truth is: not a whole lot.

CIM, which stands for Common Information Model, is an object-oriented, open-source standard for retrieving, displaying, and managing computer, network, application, and services information.

WMI, which stands for Windows Management Instrumentation, is Microsoft's own implementation of CIM and has been around since Windows NT 4.0. Originally, Microsoft used DCOM (Distributed COM) and RPC (Remote Procedure Call) to allow remote connections, but this had shortcomings when traversing networks. Starting with Windows 8 and Server 2012, Microsoft moved to WSMan (Web Services Management) for remote management, though older protocols are still supported for backward compatibility.

So, how different are these two commands? Let's look at an example:

Get-WmiObject win32_processor | Format-List



cimwmi2

Get-CimInstance win32_processor | Format-List

cimwmi3


As you can see, the data sets returned by these two commands are identical. You may come across formatting differences in the returned data, but the actual data itself will be pretty much the same.

So, why use one over the other? While there are numerous reasons why PowerShell users should start using Get-CimInstance over Get-WmiObject, including performance gains and platform support, the main reason is that Microsoft said to. If you look at Microsoft's documentation for Get-WmiObject, you'll notice that Get-CimInstance has superseded Get-WmiObject since PowerShell version 3.0. In fact, PowerShell Core, the cross-platform open-source version of PowerShell, doesn't even include WMI cmdlets. This makes sense since WMI is Windows platform-specific and PowerShell Core isn't.till, CIM is where it's at going forward.

Get-CimInstance Syntax

To figure out the syntax for Get-CimInstance, we can take a look at its help file. As always, you can return the help file for a cmdlet by typing in Get-Help, followed by the cmdlet. 

NAME Get-CimInstance SYNTAX Get-CimInstance [-ClassName] <string> [-ComputerName <string[]>] [-KeyOnly] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-QueryDialect <string>] [-Shallow] [-Filter <string>] [-Property <string[]>] [<CommonParameters>] Get-CimInstance -CimSession <CimSession[]> -ResourceUri <uri> [-KeyOnly] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-Shallow] [-Filter <string>] [-Property <string[]>] [<CommonParameters>] Get-CimInstance -CimSession <CimSession[]> -Query <string> [-ResourceUri <uri>] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-QueryDialect <string>] [-Shallow] [<CommonParameters>] Get-CimInstance [-ClassName] <string> -CimSession <CimSession[]> [-KeyOnly] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-QueryDialect <string>] [-Shallow] [-Filter <string>] [-Property <string[]>] [<CommonParameters>] Get-CimInstance [-InputObject] <ciminstance> -CimSession <CimSession[]> [-ResourceUri <uri>] [-OperationTimeoutSec <uint32>] [<CommonParameters>] Get-CimInstance [-InputObject] <ciminstance> [-ResourceUri <uri>] [-ComputerName <string[]>] [-OperationTimeoutSec <uint32>] [<CommonParameters>] Get-CimInstance -ResourceUri <uri> [-ComputerName <string[]>] [-KeyOnly] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-Shallow] [-Filter <string>] [-Property <string[]>] [<CommonParameters>] Get-CimInstance -Query <string> [-ResourceUri <uri>] [-ComputerName <string[]>] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-QueryDialect <string>] [-Shallow] [<CommonParameters>] ALIASES gcim REMARKS Get-Help cannot find the Help files for this cmdlet on this computer. It is displaying only partial help. -- To download and install Help files for the module that includes this cmdlet, use Update-Help. -- To view the Help topic for this cmdlet online, type: "Get-Help Get-CimInstance -Online" or go to https://go.microsoft.com


For the most part, our syntax will call the command and then specify a class we want to return information on. We can also specify remote computers as well as specific properties and namespaces to target.

CIM & WMI Classes

One of the difficulties with pulling data from CIM and WMI classes is knowing what the classes are and what data they contain. There is, however, a simple solution to this.

Get-CimClass

Get-CimClass will return all of the available classes you can target. If you don't specify a namespace to target, you'll default to ROOT/CIMV2. However, be warned. This command will return a pretty girthy list of classes.


cimwmi4


Consider using filters to narrow down the class list, like this:


Get-CimClass -Namespace ROOT/CIMV2 | Where-Object CimClassName -like Win32*

This filter will return only the Win32 classes from the ROOT/CIMV2 namespace. Sure, it's still a substantial list, but you can trim it down even further by including a more specific filter, like "Win32_Network*".

Examples Of Get-CimInstance

Alright, we've talked about the difference between CIM and WMI and know what we should be using CIM whenever possible. We've gone over the syntax. We've talked about the classes. Now, let's take a look at a few examples of what we can do with Get-CimInstance.

Get-CimInstance Example 1

Get-CimInstance -Class Win32_Processor


cimwmi6

In this example, we are retrieving the processor information for the local machine. This example may seem simple, but if we wanted, we could expand this to target other hardware such as motherboards, printers, memory, etc. For example, we could include the motherboard by adding the Win32_Baseboard class.

Get-CimInstance Example 2

Get-CimInstance -Class Win32_UserAccount -Filter "LocalAccount=True" -Computer odin.whiskeytime.club, heimdall.whiskeytime.club | Format-Table PSComputerName, Name, PasswordExpires


Get-CimInstance -Class Win32_UserAccount -Filter "LocalAccount=True" -Computer odin.whiskeytime.club, heimdall.whiskeytime.club | Format-Table PSComputerName, Name, PasswordExpires

cimwmi7

In this example, we're kicking things up a notch by creating a command to let us know if a remote machine has local user accounts with passwords that never expire. This is a great command to use if you need to ensure your devices don't have non-expiring password accounts on them before auditors come snooping around your network. Let's break it down.

We're returning the Win32_UserAccount class and filtering for only local accounts. Next, we're running this command against two remote computers. Lastly, we're only returning the computer name, username, and password expires properties and formatting it as a table.

Get-CimInstance Example 3


$list = Import-Csv -Path "C:\Scripts\Computer_Uptime\computers.csv" Foreach ($machine in $list){ $bootTime = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $machine.computer | Select-Object -ExpandProperty LastBootupTime $upTime = New-TimeSpan -Start $bootTime $days = [int]$upTime.TotalDays Write-Output "$($machine.computer) has been up for $days days." }

cimwmi8


For this last example, we're pulling a list of computers from a CSV file and checking to see how long they've been online. Before we get into the script, this is what the CSV looks like.

cimwmi9


As you can see, the CSV file simply contains one column consisting of computer names which we'll use to target with our script. Now, let's see how the script works.

  1. First, we're assigning the data from our CSV file to the $list variable. 

  2. Next, we're using a Foreach loop to iterate through all the computers in $list. Inside the Foreach loop, we are using Get-CimInstance to return the Win32_OperatingSystem class for the remote computer. 

  3. Then, we take the LastBootupTime property from that class, create a New-TimeSpan object and assign it to the $upTime variable. 

  4. Lastly, we're converting the $upTime variable to days instead of hours or minutes, then outputting the computer name with its total uptime in days.

This script is great for ensuring your users are turning off or restarting their computers every once in a while. If you're a firm believer of full contact IT, you could take this a step further by forcing the computers to reboot during non-work hours once they've been online for so many days. 

Wrapping Up

Believe me when I say this article barely scratches the surface of what's possible with CIM and WMI. You could spend days and weeks exploring the treasure trove of data that's accessible with Get-CimInstance. Whatever computer information you're looking for, CIM and WMI is where you'll find it, and Get-CimInstance is how you'll get it.

Brock Bingham candid headshot
Brock Bingham

Born in the '80s and raised by his NES, Brock quickly fell in love with everything tech. With over 15 years of IT experience, Brock now enjoys the life of luxury as a renowned tech blogger and receiver of many Dundie Awards. In his free time, Brock enjoys adventuring with his wife, kids, and dogs, while dreaming of retirement.

Related articles