CIM/WMI: Querying and Managing Windows Systems

PowerShell Intermediate/Advanced

Chapter 6 · CIM/WMI: Querying and Managing Windows Systems

Windows exposes an enormous amount of its own state — hardware, OS details, disks, running processes, installed software — as a queryable, database-like management layer: WMI (Windows Management Instrumentation). PowerShell's modern way in is Get-CimInstance, and one detail from Chapter 3 turns out to matter here too: CIM queries travel over the exact same WinRM infrastructure Chapter 3's own remoting used, which is the real reason CIM replaced WMI's older cmdlet family rather than just renaming it.

Get-CimInstance: Querying System State

Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object Caption, Version, OSArchitecture Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object DeviceID, @{Name="FreeGB"; Expression={ [math]::Round($_.FreeSpace / 1GB, 2) }}

Win32_OperatingSystem, Win32_LogicalDisk, Win32_ComputerSystem, Win32_BIOS, and Win32_Process are among the most commonly used WMI classes — each one a real, queryable table of system state, returned as ordinary PowerShell objects Chapter 3's Where-Object/Select-Object already know how to work with.

WQL: -Filter and -Query

# -Filter — a simplified, single-condition shorthand Get-CimInstance -ClassName Win32_Process -Filter "Name='chrome.exe'" # -Query — full WQL (WMI Query Language), SQL-like syntax, for anything more complex Get-CimInstance -Query "SELECT Name, ProcessId FROM Win32_Process WHERE Name='chrome.exe'"

Invoking Methods: Invoke-CimMethod

WMI classes aren't just read-only data — many expose real methods too, invoked directly rather than through a dedicated cmdlet:

# Calling a class-level method, with arguments Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = "notepad.exe" } # Calling a method on a specific instance you already queried $os = Get-CimInstance -ClassName Win32_OperatingSystem Invoke-CimMethod -InputObject $os -MethodName Reboot

Remote Queries: The Same WinRM Infrastructure as Chapter 3

Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName Server01 # A reusable CIM session — the same pattern as Chapter 3's own New-PSSession $cimSession = New-CimSession -ComputerName Server01 Get-CimInstance -ClassName Win32_LogicalDisk -CimSession $cimSession
The central fact this chapter is built on
Get-CimInstance isn't just Get-WmiObject under a new name — it's a genuine protocol upgrade. CIM travels over WSMan, the exact same WinRM transport Chapter 3's remoting already uses, which is why remote CIM queries need the same one-time Enable-PSRemoting setup and the same firewall rule, rather than a separate, older set of exceptions. Get-WmiObject, by contrast, used DCOM — an older, largely firewall-unfriendly protocol that needs its own separate configuration to punch through most networks. New-CimSession even mirrors Chapter 3's own New-PSSession directly: a reusable, persistent connection instead of reconnecting from scratch on every single call.

Get-WmiObject vs. Get-CimInstance

Get-WmiObject (legacy)Get-CimInstance (modern)
ProtocolDCOM — older, often firewall-unfriendlyWSMan/WinRM — the same as Chapter 3's remoting
AvailabilityWindows PowerShell 5.1 onlyAvailable in PowerShell 7+ as well
Session reuseNo real persistent-session conceptNew-CimSession — reusable, like New-PSSession

Get-WmiObject was fully removed from PowerShell 7+ — not deprecated-but-working, genuinely gone — which makes Get-CimInstance the only real option for any script expected to run on a modern PowerShell install.

Win32_Product is slow for a real, documented reason — avoid it
Querying Win32_Product to list installed software is a well-known, Microsoft-acknowledged trap: the query itself triggers Windows Installer to run a consistency check against every single installed MSI package on the machine — genuinely slow, and capable of triggering unexpected repair prompts on machines with a lot of software installed. Reading installed programs from the registry's own Uninstall keys instead — the same HKLM:/HKCU: provider Fundamentals 2 already covered — is faster and has no such side effect: Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*.
A first practical habit
Reach for -Filter first for anything expressible as one simple condition — it reads closer to plain PowerShell. Save full -Query WQL for genuinely more complex conditions -Filter can't express on its own, mirroring the same "simplified first, script-block when needed" instinct Chapter 1's own Where-Object material already built.

Hands-On Exercises

Exercise 1

Explain why Get-WmiObject doesn't work at all in PowerShell 7+ while Get-CimInstance works fine, referencing the underlying protocol each one actually uses.

📄 View solution
Exercise 2

Explain why running Get-CimInstance -ClassName Win32_Product to list installed software is a real, documented bad idea, and what alternative this chapter recommends instead.

📄 View solution
Exercise 3

Write a Get-CimInstance query (using either -Filter or -Query) that finds all Win32_Process instances named notepad.exe. Explain which form you chose and why.

📄 View solution

Chapter 6 Quick Reference

  • Get-CimInstance -ClassName — queries a WMI class as ordinary PowerShell objects
  • -Filter / -Query — a simplified single-condition shorthand, or full WQL for anything more complex
  • Invoke-CimMethod — calls a real method on a WMI class or a queried instance
  • CIM uses WSMan/WinRM — the same transport, setup, and firewall rule as Chapter 3's own remoting
  • New-CimSession — a reusable remote connection, mirroring Chapter 3's own New-PSSession
  • Get-WmiObject is fully removed from PowerShell 7+ — used DCOM, an older, firewall-unfriendly protocol; Get-CimInstance is the only real modern option
  • Win32_Product is a real trap — triggers a consistency check against every installed MSI; read the registry's Uninstall keys instead
  • Next chapter: Calling APIs: Invoke-RestMethod & Working with JSON