Introduction to WMI on Windows Server 2019

Windows Management Instrumentation (WMI) is a core Windows infrastructure technology that provides a standardized interface for managing and monitoring Windows systems. WMI implements the Distributed Management Task Force (DMTF) Common Information Model (CIM) standard, making it an industry-standard approach to system management. On Windows Server 2019, WMI exposes thousands of classes organized into namespaces that provide access to hardware information, operating system configuration, running processes, services, event logs, network configuration, and virtually every manageable aspect of the system. Administrators use WMI via PowerShell’s Get-WmiObject and Get-CimInstance cmdlets, through scripting languages, and through management tools including System Center Operations Manager and SCCM.

Understanding WMI Architecture

WMI uses a hierarchical namespace structure. The primary namespace for most management tasks is rootCIMv2, which contains classes representing the operating system, hardware, and processes. Other important namespaces include rootMicrosoftWindowsStorage for storage management, rootRSOP for Resultant Set of Policy data, rootMicrosoftWindowsDefender for Defender Antivirus, and rootMicrosoftWindowsHardwareManagement for hardware health. List available namespaces:

Get-CimInstance -Namespace root -ClassName __Namespace | Select-Object Name
Get-WmiObject -Namespace root -Class __Namespace | Select-Object Name

List all classes in the rootCIMv2 namespace:

Get-CimClass -Namespace root/CIMv2 | Select-Object CimClassName | Where-Object {$_.CimClassName -like "Win32*"} | Sort-Object CimClassName | Format-Table

Querying System Information with WMI

Use WMI to retrieve comprehensive system information. The preferred modern approach uses Get-CimInstance which uses WinRM transport instead of DCOM:

Get-CimInstance Win32_ComputerSystem | Select-Object Name, Domain, Manufacturer, Model, TotalPhysicalMemory, NumberOfLogicalProcessors, DNSHostName
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber, InstallDate, LastBootUpTime, TotalVisibleMemorySize, FreePhysicalMemory, OSArchitecture
Get-CimInstance Win32_BIOS | Select-Object Manufacturer, Name, SerialNumber, SMBIOSBIOSVersion, ReleaseDate
Get-CimInstance Win32_Processor | Select-Object Name, MaxClockSpeed, NumberOfCores, NumberOfLogicalProcessors, LoadPercentage, SocketDesignation
Get-CimInstance Win32_PhysicalMemory | Select-Object BankLabel, Capacity, Speed, Manufacturer, PartNumber | ForEach-Object {$_.Capacity = $_.Capacity/1GB; $_}

Managing Services via WMI

WMI provides complete service management capabilities including starting, stopping, pausing, and changing service configuration:

Get-CimInstance Win32_Service | Where-Object {$_.State -eq "Running"} | Select-Object Name, DisplayName, StartMode, PathName | Format-Table -AutoSize
Get-CimInstance Win32_Service -Filter "Name='Spooler'" | Select-Object Name, State, StartMode, StartName
$service = Get-CimInstance Win32_Service -Filter "Name='Spooler'"
Invoke-CimMethod -InputObject $service -MethodName "StopService"
Invoke-CimMethod -InputObject $service -MethodName "StartService"
Invoke-CimMethod -InputObject $service -MethodName "ChangeStartMode" -Arguments @{StartMode="Disabled"}

Find services running with non-system accounts (important for security auditing):

Get-CimInstance Win32_Service | Where-Object {$_.StartName -notmatch "LocalSystem|NetworkService|LocalService|NT AUTHORITY|NT SERVICE"} | Select-Object Name, DisplayName, StartName, State

Process Management with WMI

WMI provides detailed process information and management capabilities. Win32_Process includes the full command line, creation date, and parent process ID:

Get-CimInstance Win32_Process | Select-Object ProcessId, Name, CommandLine, CreationDate | Sort-Object CreationDate -Descending | Format-Table -AutoSize
# Top 10 processes by virtual memory size
Get-CimInstance Win32_Process | Sort-Object VirtualSize -Descending | Select-Object -First 10 ProcessId, Name, VirtualSize, WorkingSetSize | ForEach-Object {
    [PSCustomObject]@{
        PID = $_.ProcessId
        Name = $_.Name
        VirtualSizeMB = [math]::Round($_.VirtualSize/1MB, 0)
        WorkingSetMB = [math]::Round($_.WorkingSetSize/1MB, 0)
    }
} | Format-Table

Terminate a process via WMI:

$process = Get-CimInstance Win32_Process -Filter "Name='notepad.exe'"
Invoke-CimMethod -InputObject $process -MethodName "Terminate"

Network Configuration via WMI

Query and modify network configuration using WMI classes:

Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true} | Select-Object Description, IPAddress, DefaultIPGateway, DNSServerSearchOrder, MACAddress
Get-CimInstance Win32_NetworkAdapter | Where-Object {$_.PhysicalAdapter -eq $true} | Select-Object Name, Speed, MACAddress, NetConnectionStatus, NetConnectionID
Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled} | ForEach-Object {
    [PSCustomObject]@{
        Adapter = $_.Description
        IP = $_.IPAddress -join ", "
        Mask = $_.IPSubnet -join ", "
        Gateway = $_.DefaultIPGateway -join ", "
        DNS = $_.DNSServerSearchOrder -join ", "
        DHCP = $_.DHCPEnabled
    }
}

Configure a static IP address via WMI:

$nic = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -and $_.Description -like "*Ethernet*"} | Select-Object -First 1
$nic.EnableStatic("192.168.1.100", "255.255.255.0")
$nic.SetGateways("192.168.1.1", 1)
$nic.SetDNSServerSearchOrder(@("192.168.1.10","192.168.1.11"))

WMI Event Subscriptions for Monitoring

WMI supports event subscriptions that trigger actions when specific conditions occur. Create a permanent WMI event subscription to detect new processes being launched, useful for security monitoring:

$query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"
$filter = Set-WmiInstance -Namespace rootsubscription -Class __EventFilter -Arguments @{
    Name = "ProcessCreationFilter"
    EventNamespace = "rootcimv2"
    QueryLanguage = "WQL"
    Query = $query
}
$consumer = Set-WmiInstance -Namespace rootsubscription -Class LogFileEventConsumer -Arguments @{
    Name = "ProcessCreationConsumer"
    FileName = "C:WMILogsProcessCreation.log"
    Text = "New process: %TargetInstance.Name% PID: %TargetInstance.ProcessId% at %TIME_CREATED%"
}
Set-WmiInstance -Namespace rootsubscription -Class __FilterToConsumerBinding -Arguments @{
    Filter = $filter
    Consumer = $consumer
}

WMI Security and DCOM Configuration

Configure WMI security to allow remote management from specific accounts while preventing unauthorized access. WMI uses DCOM for remote connections. Configure DCOM access permissions:

dcomcnfg.exe  # Opens Component Services for GUI configuration
# Or configure via WMI Security in the WMI Control snap-in (wmimgmt.msc)

Grant a non-administrative user read access to WMI namespaces:

$wmiNS = "rootcimv2"
$account = "CONTOSOMonitorUser"
$wmisecurity = Get-WmiObject -Namespace $wmiNS -Class __systemsecurity
$binarySD = @($null)
$wmisecurity.GetSD($binarySD) | Out-Null
$converter = New-Object System.Management.ManagementClass Win32_SecurityDescriptorHelper
$sd = $converter.BinarySDToSDDL($binarySD[0])
Write-Host "Current WMI Security Descriptor: $($sd.SDDL)"

Configure Windows Firewall to allow WMI remote queries from specific management hosts:

Enable-NetFirewallRule -DisplayGroup "Windows Management Instrumentation (WMI)"
New-NetFirewallRule -DisplayName "WMI Remote Management" -Direction Inbound -Protocol TCP -LocalPort 135 -Action Allow -RemoteAddress 192.168.1.100
Set-NetFirewallRule -DisplayGroup "Windows Management Instrumentation (WMI)" -Enabled True -Profile Domain

Remote WMI Queries

Query WMI on remote Windows Server 2019 machines using Get-CimInstance with CIM sessions for efficient multi-server querying:

$servers = "Server01","Server02","Server03"
$cred = Get-Credential
$sessions = New-CimSession -ComputerName $servers -Credential $cred
Get-CimInstance Win32_OperatingSystem -CimSession $sessions | Select-Object PSComputerName, Caption, FreePhysicalMemory, LastBootUpTime
Get-CimInstance Win32_Service -CimSession $sessions -Filter "State='Stopped' AND StartMode='Auto'" | Select-Object PSComputerName, Name, DisplayName, StartMode
Remove-CimSession $sessions

WMI on Windows Server 2019 remains a cornerstone technology for system management, automation, and monitoring, providing rich programmatic access to all aspects of Windows server configuration and health through standardized, queryable classes.