PowerShell Genie
Learn WMI Queries

Querying WMI with PowerShell

Everything about a Windows machine is queryable: OS version, disks, services, BIOS, hotfixes. Get-CimInstance is the modern way to ask — and it works remotely over WinRM, where the old WMI cmdlet cannot follow.

Intermediate 6 min read Works in Windows PowerShell 5.1 and PowerShell 7 · Get-WmiObject is Windows PowerShell only

Documentation: Get-CimInstance documentation

What WMI and CIM are

WMI — Windows Management Instrumentation — is the database Windows keeps about itself: hardware, operating system, services, processes, disks, network adapters, installed updates. A WMI class is one table in that database: Win32_OperatingSystem is the OS row, Win32_LogicalDisk is one row per drive, Win32_Service is one row per service.

Two cmdlets read it. Get-WmiObject is the original: it speaks DCOM, works only in Windows PowerShell 5.1, and was removed from PowerShell 7. Get-CimInstance is the replacement: it speaks WS-MAN, the same protocol as remoting, works in 5.1 and 7, and queries remote machines through WinRM without DCOM firewall holes.

The rule is simple: write Get-CimInstance for anything new. Get-WmiObject appears only in old scripts and old blog posts — when you meet one, translate it: Get-WmiObject -Class Win32_LogicalDisk becomes Get-CimInstance -ClassName Win32_LogicalDisk.

See the objects move

Inspect this authored example with fictional data in the bounded browser model. The numbered stages show how its objects change.

Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" |
  1. Stage 1Get-CimInstance -ClassName Win32_LogicalDisk Try it: list local disks

    Query a class

    Name the class, then narrow the rows. -Filter runs on the target machine, so only matching rows travel back — always prefer it to piping everything through Where-Object:

    1PS> Get-CimInstance -ClassName Win32_OperatingSystem |
    2PS> Select-Object Caption, Version, LastBootUpTime
    3PS> Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" |
    4PS> Select-Object DeviceID, FreeSpace, Size
    5PS> Get-CimInstance -Query "SELECT Name, State FROM Win32_Service WHERE State='Stopped'"

    DriveType 3 means a local fixed disk; 2 is removable, 4 is network, 5 is optical. The -Query form is WQL, WMI's SQL-like language, for conditions -Filter cannot express. For remote machines, add -ComputerName and a CIM session: New-CimSession -ComputerName SRV01, then Get-CimInstance -CimSession $s -ClassName Win32_OperatingSystem. Remote CIM needs WinRM enabled on the target — Enable-PSRemoting on the server, and the client must trust the host or be domain-joined.

    Common classes worth memorizing: Win32_ComputerSystem (model, manufacturer, total memory), Win32_BIOS (serial number), Win32_Process, Win32_Service, Win32_QuickFixEngineering (installed hotfixes), Win32_NetworkAdapterConfiguration (IP settings, filter IPEnabled=TRUE).

    Try it: list local disks

    List every local disk with its free and total space in GB:

    1PS> Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" |
    2PS> Select-Object DeviceID,
    3PS> @{N='FreeGB';E={[math]::Round($_.FreeSpace / 1GB, 1)}},
    4PS> @{N='SizeGB';E={[math]::Round($_.Size / 1GB, 1)}}

    Each row is one local disk: DeviceID is the drive letter, FreeGB and SizeGB are calculated properties dividing the raw byte counts by 1GB and rounding to one decimal. A machine with only a C: drive returns one row; servers return one per volume.

    Common mistakes

    • Using Get-WmiObject in PowerShell 7. It does not exist there. The command is not found, full stop. Use Get-CimInstance and -ClassName instead of -Class.
    • Filtering client-side. Piping every Win32_Process row through Where-Object pulls the whole table across the network first. -Filter narrows it on the target.
    • Wrong DriveType. DriveType=3 is a local disk. Forgetting the filter returns CD drives, USB sticks and mapped network drives in the same list.
    • Remote queries without WinRM. Get-CimInstance -ComputerName fails when the target has no WinRM listener. Run Enable-PSRemoting on the target first, and check Test-WSMan.
    • Reading bytes as GB. FreeSpace and Size are bytes. Dividing by 1GB — not 1000 — gives the gibibytes Windows itself reports.

    Your turn

    On your own machine, list the installed hotfixes with Win32_QuickFixEngineering, showing HotFixID and InstalledOn, newest first. Then query Win32_BIOS for the serial number — the same value asset tags are built from.

    Prove it: write it alone

    Blank editor. No starter, no hints. Write a query that returns every stopped service on the local machine using WQL -Query, showing only Name and State — then rewrite it with -ClassName and -Filter instead.

    Practise this

    Query local disks

    Return the device ID, free space and size of every local disk on this machine.

    Review the lesson

    Recap

    WMI is Windows' database about itself; Get-CimInstance is the modern reader, over WinRM, in both 5.1 and 7. Name the class, filter server-side with -Filter, use WQL -Query for complex conditions, and reach remote machines with CIM sessions. Get-WmiObject belongs to old scripts only — translate it, don't copy it.

    Genie guideWMI Queries with PowerShell

    Get-CimInstance asks Windows about itself: disks, OS, services, BIOS. Filter server-side with -Filter, and use CIM sessions for remote machines — Get-WmiObject does not exist in PowerShell 7.

    Stuck? Re-read the section, then try the filter yourself.