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.
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:
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.
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.
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 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.
Consider using filters to narrow down the class list, like this:
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
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
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
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.
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.
First, we're assigning the data from our CSV file to the $list variable.
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.
Then, we take the LastBootupTime property from that class, create a New-TimeSpan object and assign it to the $upTime variable.
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.
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.
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.