How to Use WMI on Windows Server 2012 R2

Windows Management Instrumentation (WMI) is Microsoft’s implementation of the Web-Based Enterprise Management (WBEM) standard and the central repository of management information on Windows systems. WMI exposes virtually every aspect of a Windows Server 2012 R2 system — hardware inventory, operating system properties, installed software, running processes, services, network configuration, disk information, and much more — through a structured, queryable interface accessible via PowerShell, VBScript, and remote management tools.

In Windows Server 2012 R2, WMI runs alongside its successor CIM (Common Information Model), and PowerShell 4.0 provides both the legacy Get-WmiObject cmdlet and the newer, preferred Get-CimInstance cmdlet. Both access WMI data, but CIM cmdlets use the WS-Management protocol and are more efficient for remote queries. This guide covers the most practical WMI use cases for server administration, including hardware inventory, service management, process monitoring, and remote WMI queries.

Prerequisites

– Windows Server 2012 R2 with PowerShell 4.0
– Administrative credentials on the local or remote server
– WMI service (winmgmt) running on target systems
– For remote WMI: Windows Firewall exceptions for WMI (TCP port 135 plus dynamic RPC ports) or WinRM configured
– Basic understanding of WMI namespaces and classes

Step 1: Verify WMI Service Status

The WMI service (Windows Management Instrumentation) must be running. Check its status:

Get-Service winmgmt | Select-Object Name, DisplayName, Status, StartType

If it is stopped, start it:

Start-Service winmgmt
Set-Service winmgmt -StartupType Automatic

Run a quick test query to confirm WMI is responding:

Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object Name, Manufacturer, Model

Step 2: Explore WMI Namespaces and Classes

WMI is organized into namespaces. The most commonly used is rootCIMV2, which contains classes for OS, hardware, and software management. Explore available namespaces:

# List root namespaces
Get-CimInstance -Namespace root -ClassName __Namespace | Select-Object Name | Sort-Object Name

List all classes in the CIMV2 namespace:

Get-CimClass -Namespace rootCIMV2 | Select-Object CimClassName | Sort-Object CimClassName | Where-Object { $_.CimClassName -like "Win32_*" }

Inspect the properties of a specific class before querying it:

Get-CimClass -ClassName Win32_LogicalDisk | Select-Object -ExpandProperty CimClassProperties | Select-Object Name, CimType

Step 3: Hardware and System Inventory with WMI

WMI is the most comprehensive source of hardware information on Windows. Gather a complete system inventory:

# Computer system information
Get-CimInstance Win32_ComputerSystem | Select-Object Name, Manufacturer, Model, SystemType, TotalPhysicalMemory

# BIOS information
Get-CimInstance Win32_BIOS | Select-Object Manufacturer, Name, Version, SerialNumber, ReleaseDate

# Processor information
Get-CimInstance Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed, LoadPercentage

# Physical memory modules
Get-CimInstance Win32_PhysicalMemory | Select-Object BankLabel, Capacity, Speed, Manufacturer, PartNumber

# Total installed RAM in GB
$totalRAM = (Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB
Write-Host "Total RAM: $([math]::Round($totalRAM, 2)) GB"

Step 4: Disk and Storage Information

WMI provides rich disk and partition information through multiple classes:

# Logical disk (drive letters) with free space
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, VolumeName,
    @{N="SizeGB"; E={[math]::Round($_.Size/1GB,2)}},
    @{N="FreeGB"; E={[math]::Round($_.FreeSpace/1GB,2)}},
    @{N="UsedPct"; E={[math]::Round((($_.Size-$_.FreeSpace)/$_.Size)*100,1)}}

# Physical disk drives
Get-CimInstance Win32_DiskDrive | Select-Object Model, Size, InterfaceType, MediaType, Status

# Disk partitions
Get-CimInstance Win32_DiskPartition | Select-Object DiskIndex, Name, Size, Type, BootPartition

# Volume information
Get-CimInstance Win32_Volume -Filter "DriveType=3" | Select-Object DriveLetter, Label, FileSystem,
    @{N="CapacityGB"; E={[math]::Round($_.Capacity/1GB,2)}},
    @{N="FreeGB"; E={[math]::Round($_.FreeSpace/1GB,2)}}

Step 5: Network Configuration Information

Retrieve detailed network adapter configuration from WMI:

# Network adapters with IP configuration
Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "IPEnabled=True" | ForEach-Object {
    [PSCustomObject]@{
        Description = $_.Description
        MACAddress  = $_.MACAddress
        IPAddress   = $_.IPAddress -join ", "
        SubnetMask  = $_.IPSubnet -join ", "
        DefaultGW   = $_.DefaultIPGateway -join ", "
        DNS         = $_.DNSServerSearchOrder -join ", "
        DHCP        = $_.DHCPEnabled
    }
}

# All network adapters (including disabled)
Get-CimInstance Win32_NetworkAdapter | Select-Object Name, MACAddress, AdapterType, Speed, NetEnabled

Step 6: Operating System and Uptime Information

Query OS properties and calculate system uptime:

$os = Get-CimInstance Win32_OperatingSystem
$uptime = (Get-Date) - $os.LastBootUpTime

[PSCustomObject]@{
    ComputerName    = $os.CSName
    OSName          = $os.Caption
    ServicePack     = $os.CSDVersion
    Architecture    = $os.OSArchitecture
    BuildNumber     = $os.BuildNumber
    InstallDate     = $os.InstallDate
    LastBoot        = $os.LastBootUpTime
    UptimeDays      = [math]::Round($uptime.TotalDays, 1)
    TotalMemoryGB   = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
    FreeMemoryGB    = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
    TotalVirtualGB  = [math]::Round($os.TotalVirtualMemorySize / 1MB, 2)
    FreeVirtualGB   = [math]::Round($os.FreeVirtualMemory / 1MB, 2)
}

Step 7: Process and Service Management with WMI

WMI provides process and service information with additional detail not available from Get-Process:

# List top 10 processes by working set memory
Get-CimInstance Win32_Process | Sort-Object WorkingSetSize -Descending | Select-Object -First 10 `
    Name, ProcessId,
    @{N="MemoryMB"; E={[math]::Round($_.WorkingSetSize/1MB,1)}},
    @{N="CpuSecs"; E={[math]::Round($_.KernelModeTime/10000000,2)}},
    CommandLine

# Get the owner of a process (who launched it)
Get-CimInstance Win32_Process -Filter "Name='notepad.exe'" | ForEach-Object {
    $owner = Invoke-CimMethod -InputObject $_ -MethodName GetOwner
    "$($_.Name) ($($_.ProcessId)) — Owner: $($owner.Domain)$($owner.User)"
}

# List services with their executable paths
Get-CimInstance Win32_Service | Select-Object Name, DisplayName, State, StartMode, PathName | Sort-Object Name

Step 8: Installed Software Inventory

WMI can enumerate installed software via Win32_Product, though this class triggers Windows Installer repair checks and is slow. For fast read-only inventory, query the registry instead via WMI:

# Using Win32_Product (slow but comprehensive)
Get-CimInstance Win32_Product | Select-Object Name, Version, Vendor, InstallDate | Sort-Object Name

# Alternative: query registry for installed programs (faster)
$regPath = "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall*"
Get-ItemProperty $regPath | Where-Object { $_.DisplayName } |
    Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |
    Sort-Object DisplayName

Step 9: Remote WMI Queries

Query WMI on remote servers using CIM sessions, which use WS-Management (WinRM) and are more firewall-friendly than DCOM-based WMI:

# Create a CIM session to a remote server
$session = New-CimSession -ComputerName "Server01"

# Query the remote server
Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem | Select-Object CSName, Caption, LastBootUpTime

# Query multiple servers simultaneously
$servers = @("Server01","Server02","Server03")
$sessions = New-CimSession -ComputerName $servers

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

# Clean up sessions
Remove-CimSession $sessions

Step 10: WMI Event Subscriptions

WMI supports permanent event subscriptions that execute actions when system events occur — a powerful automation tool:

# Create a WMI event query that watches for a specific process to start
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = 'suspicious.exe'"

# Register a temporary event subscription (valid for current PowerShell session)
Register-CimIndicationEvent -Query $query -Action {
    $process = $EventArgs.NewEvent.TargetInstance
    Write-EventLog -LogName Application -Source "WMI Monitor" -EventId 9001 -EntryType Warning -Message "Suspicious process started: PID $($process.ProcessId)"
} -SourceIdentifier "ProcessWatch"

# List registered event subscriptions
Get-EventSubscriber | Select-Object SubscriptionId, SourceIdentifier, EventName

# Remove when no longer needed
Unregister-Event -SourceIdentifier "ProcessWatch"

Troubleshooting WMI Issues

If WMI queries fail or return incomplete data, the WMI repository may be corrupt. Verify its integrity:

winmgmt /verifyrepository

If verification fails, rebuild the repository (this requires a service restart and may take several minutes):

winmgmt /resetrepository

For remote WMI connectivity issues, verify firewall exceptions are in place:

netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=yes

Summary

WMI on Windows Server 2012 R2 is an indispensable tool for server administration, providing programmatic access to virtually every aspect of system state and configuration. Through PowerShell’s Get-CimInstance cmdlet and CIM sessions, administrators can build comprehensive inventory scripts, automate routine checks, monitor for security events using WMI event subscriptions, and gather remote server data efficiently. Understanding the key WMI classes — Win32_ComputerSystem, Win32_LogicalDisk, Win32_Process, Win32_Service, Win32_OperatingSystem — and how to filter and format their output enables sophisticated automation that would otherwise require expensive third-party monitoring tools.