Whenever we need to discover just about any information about a Windows computer and it’s components, we can do so with Get-WmiObject
.
Not only reading, by leveraging WMI methods, Get-WmiObject
can also run actions on local or remote systems as well. This cmdlet is one of a couple in PowerShell that can work with the WMI repository to make managing lots of systems a whole lot easier.
Discovering Classes with Get-WmiObject
At it’s most basic this cmdlet can query information from a local computer. All you’ll need to know is the namespace (probably root\cimv2
which is default) and the WMI class where the information you’re looking for is located.
There are thousands of classes, and you probably don’t know which class you’d like to use yet. Using Get-WmiObject
, we can query all of the available classes in a namespace. Using Get-WmiObject -List
, you’ll be able to see all of the classes in the root\cimv2
namespace. If you need to check classes in another namespace, you can always use the Namespace
parameter along with that as well.
PS> Get-WmiObject -List
NameSpace: ROOT\cimv2
Name Methods Properties
CIM_Indication {} {CorrelatedIndications, IndicationFilterName, IndicationIde...
CIM_ClassIndication {} {ClassDefinition, CorrelatedIndications, IndicationFilterNa........
Getting WMI Properties
Once you’ve got the class, it’s then time to investigate and see what properties are in that class. Perhaps I’d like to see what operating system a computer is running. I might be building a report and would like to see what a remote machine is running. Get-WmiObject
has a ComputerName
parameter where you can specify one or more remote computers rather than locally.
My remote computer is a domain controller called DC. I’ll look at the Win32_OperatingSystem
class to see what properties are in there.
PS> Get-WmiObject -ComputerName DC -Class Win32_OperatingSystem
SystemDirectory : C:\Windows\system32
Organization :
BuildNumber : 9600
RegisteredUser : Windows User
SerialNumber : 00252-00108-14656-AA864
Version : 6.3.9600
That’s useful information, but I don’t see the operating system name. Similar to many other PowerShell outputs, you do not see all of the properties. For that, we’ll have to use Select-Object
to return all of the properties.
Get-WmiObject -ComputerName DC -Class Win32_OperatingSystem | Select-Object -Property *
I can now see a property called Caption
that lets me know the version of Windows.
PS> (Get-WmiObject -ComputerName DC -Class Win32_OperatingSystem | Select-Object -Property *).Caption Microsoft Windows Server 2012 R2 Standard
Finding WMI Properties
What if you aren’t looking for a specific property but rather a property that matches a specific value. For example, we can query all of the instances in the CIM_DataFile
class, but that would return every file on the system! Instead, we can filter instances by value using either the Filter
or the Query
parameter. Let’s go over both.
Using the CIM_DataFile
as an example, maybe I want only to find instances that represent compressed files. Since the Compressed
property is a property on each instance and it’s a boolean value, I can use the Filter
parameter to send the filter directly to the WMI provider only returning instances that have a Compressed
property of True
.
Get-WmiObject -Class CIM_DataFile -Filter "Compressed = 'True'"
If you know WQL, you can also select the class and specify the “filter” on your own by crafting your own WQL query as well.
Get-WmiObject -Query "SELECT * FROM CIM_DataFile WHERE Compressed = 'True'"
Invoking WMI Methods
Get-WmiObject
not only can read information from WMI, but it can also facilitate invoking WMI methods. One common WMI method that’s invoked is the Create
method on the Win32_Process
class. There are a few different ways to invoke WMI methods such as using Invoke-WmiMethod
, but this can be done with Get-WmiObject
as well. We just need to capture a WMI instance and then call the method on that object.
Here’s an example of remotely starting notepad.exe on a remote computer. As a bonus, we’re using an alternate credential to do so as well!
$cred = get-credential
$process = Get-WmiObject -Query "SELECT * FROM Meta_Class WHERE __Class = 'Win32_Process'" -namespace "root\cimv2" -computername 'FOO' -credential $cred $process.Create( "notepad.exe" )
WMI, DCOM, and PowerShell Remoting
One last thing to point out is that this cmdlet’s successor: Get-CimInstance
. Although Get-CimInstance
does provide some advantages to using PowerShell Remoting as it’s default remote connectivity protocol, Get-WmiObject
is sometimes easier to use.
Get-WmiObject
uses DCOM to communicate with remote computers and is also usually available as well. Otherwise, you’ll need to enable PowerShell Remoting on remote endpoints when wanting to use Get-CimInstance
via WSMAN.
For a full breakdown, check out the Microsoft documentation.