Understanding WMI Namespaces

WMI organizes its classes in a hierarchical namespace. To find useful information, you need to know a Class Name plus the Namespace where it lives.

WMI organizes its classes in a hierarchical namespace. To find useful information, you need to know a Class Name plus the Namespace where it lives.

A Namespace organizes information similar to folders in a filesystem. The top “folder” of the WMI namespace is always called “root”.

Exploring Namespaces

WMI represents namespaces as instances of the class: __Namespace. This class starts with 2 (two) underscores. All internal WMI classes are marked that way.

Finding Child Namespaces of a Namespace
Get-CimInstance -ClassName __Namespace 

The result looks similar to this:

Name             PSComputerName
----             --------------
mdm                            
ms_40c                         
Security                       
ms_410                         
power                          
ms_413                         
ms_409                         
TerminalServices               
ms_407

WMI namespaces are extensible, so you may see more (or less) namespaces, depending on the kind and type of operating system (client vs. server) and the software you installed.

Get-CimInstance cannot search recursively through all namespaces. It always searches only one namespace, and if you don’t specify one, it uses the default namespace root/cimv2.

So what you see are the immediate child namespaces of root/cimv2. Some of these serve a special purpose: namespaces that start with ms_ are just language-specific extensions. The number following is the country code, and these namespaces contain localized documentation only.

To find real namespaces with potentially interesting classes in them, exclude any namespace name that starts with *“ms_” followed by at least two numbers.

Excluding Localization Namespaces
Get-CimInstance -ClassName __Namespace |
  Where-Object Name -NotMatch '^ms_\d{2}'

The result looks similar to this:

Name             PSComputerName
----             --------------
mdm                            
Security                       
power                          
TerminalServices  

Apparently, the namespace root/cimv2 has four child namespaces.

Listing All Available Namespaces

To find all namespaces, you need to start the search at the top namespace root and then search recursively through all child namespaces.

Listing all namespaces

Since recursion is hard to debug and has the risk of running into out-of-memory errors when nesting levels are too deep, I am using a better alternative: a Queue.

Some namespaces are protected, so in order to get a full list, make sure you run below code with Administrator privileges.

# create a new queue
$namespaces = [System.Collections.Queue]::new()

# add an initial namespace to the queue
# any namespace in the queue will later be processed
$namespaces.Enqueue('root')

# process all elements on the queue until all are taken
While ($namespaces.Count -gt 0 -and ($current = $namespaces.Dequeue()))
{
    # find child namespaces
    Get-CimInstance -Namespace $current -ClassName __Namespace -ErrorAction Ignore |
    # ignore localization namespaces
    Where-Object Name -NotMatch '^ms_\d{2}' |
    ForEach-Object {
        # construct the full namespace name
        $childnamespace = '{0}\{1}' -f $current, $_.Name
        # add namespace to queue
        $namespaces.Enqueue($childnamespace)
    }

    # output current namespace
    $current
}

The result on an average Windows 10 client looks similar to this:

root
root\subscription
root\DEFAULT
root\CIMV2
root\msdtc
root\Cli
root\Intel_ME
root\SECURITY
root\SecurityCenter2
root\RSOP
root\PEH
root\StandardCimv2
root\WMI
root\MSPS
root\directory
root\Policy
root\Interop
root\Hardware
root\ServiceModel
root\SecurityCenter
root\Microsoft
root\Appv
root\dcim
root\CIMV2\mdm
root\CIMV2\Security
root\CIMV2\power
root\CIMV2\TerminalServices
root\RSOP\User
root\RSOP\Computer
root\StandardCimv2\embedded
root\directory\LDAP
root\Microsoft\HomeNet
root\Microsoft\protectionManagement
root\Microsoft\Windows
root\Microsoft\SecurityClient
root\Microsoft\Uev
root\dcim\sysman
root\CIMV2\mdm\dmmap
root\CIMV2\Security\MicrosoftTpm
root\CIMV2\Security\MicrosoftVolumeEncryption
root\Microsoft\Windows\RemoteAccess
root\Microsoft\Windows\Dns
root\Microsoft\Windows\Powershellv3
root\Microsoft\Windows\Hgs
root\Microsoft\Windows\WindowsUpdate
root\Microsoft\Windows\DeviceGuard
root\Microsoft\Windows\TaskScheduler
root\Microsoft\Windows\DesiredStateConfigurationProxy
root\Microsoft\Windows\SmbWitness
root\Microsoft\Windows\Wdac
root\Microsoft\Windows\StorageReplica
root\Microsoft\Windows\winrm
root\Microsoft\Windows\AppBackgroundTask
root\Microsoft\Windows\DHCP
root\Microsoft\Windows\PS_MMAgent
root\Microsoft\Windows\Storage
root\Microsoft\Windows\HardwareManagement
root\Microsoft\Windows\SMB
root\Microsoft\Windows\EventTracingManagement
root\Microsoft\Windows\DesiredStateConfiguration
root\Microsoft\Windows\CI
root\Microsoft\Windows\dfsn
root\Microsoft\Windows\Defender
root\dcim\sysman\biosattributes
root\dcim\sysman\wmisecurity
root\Microsoft\Windows\RemoteAccess\Client
root\Microsoft\Windows\Storage\PT
root\Microsoft\Windows\Storage\Providers_v2
root\Microsoft\Windows\Storage\PT\Alt

Listing Classes in a Namespace

Now that you know the names of the available namespaces, Get-CimClass can list the valid class names inside of each.

List class names for namespace root\cimv2
# list all classes that live in namespace "root\cimv2"...
Get-CimClass -Namespace 'root\cimv2' | 
# take only the class name...
Select-Object -ExpandProperty CimClassName | 
# and sort the output:
Sort-Object

The result is a huge list: on an average Windows 10 client, the namespace root/cimv2 contains 1,200 classes.

Identifying Useful Classes

Because there are so many WMI classes, it is important to define a strategy to identify potentially useful classes. The class name prefix can give a clue:

Prefix Count Description
__ 53 internal WMI class used to organize WMI
CIM 286 Original class definitions
Win32 749 Extended Microsoft implementations that inherit from a CIM class
MSFT 102 Unique Microsoft class that does not inherit from a CIM class

There are a few class names that do not use prefixes. Add them to the “potentially interesting class” pile.

By excluding any class name that either starts with two underscores or with CIM_, you can eliminate a significant portion.

Classes can have relationships to each other, and these links are defined yet by other classes, similar to a database join. Typically, classes that just link two other classes have at most 3 propertes. Any of these classes can be excluded.

Exclude Performance Counters

Every performance counter has its own WMI class, so if you are not explicitly trying to read performance counter values, exclude any classname that starts with Win32_Perf.

Exclude Plug&Play Classes

Another rather large group of classes describes plug&play functionality and starts with Win32_PnP. You can safely ignore these classes in most cases because the actual plug&play devices and most of the information about them surfaces in other more specific classes.

Listing potentially useful classes in namespace cimv2
# get all classes from namespace "root/cimv2"...
Get-CimClass -Namespace 'root\cimv2' |
  # exclude classes that start with __/CIM/Win32_PnP/Win32_Perf
  Where-Object CimClassName -NotMatch '^(__|CIM_|Win32_PnP|Win32_Perf)' |
  # exclude classes with less than 4 properties...
  Where-Object { $_.CimClassProperties.Count -gt 3 } |
  # return just the class name...
  Select-Object -ExpandProperty CimClassName |
  # sort results:
  Sort-Object

This reduces the class count from 1,200 to 319 classes.