WMI classes are organized in so-called namespaces that start at “root” and work like a directory structure. The default namespace is rootcimv2, and when you do not specify a namespace, you can only see the WMI classes located in the default namespace. This is what we have been using in the past parts of this series.
There are many more namespaces with many additional WMI classes, some of which can be highly useful. Before we explore this part of WMI, be advised that you are going to tap into sparsely documented areas of Windows that are not necessarily intended for general audiences. You may have to google, and classes found here may be available on specific Windows operating systems and/or license types only.
To get a list of WMI namespaces available on your computer, run the code below:
# 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 code may run for some time, so grab a coffee. The result is the list of namespaces available on your machine and may look similar to this:
root rootsubscription rootDEFAULT rootCIMV2 rootmsdtc rootCli rootIntel_ME rootSECURITY rootHyperVCluster rootSecurityCenter2 rootRSOP rootPEH rootStandardCimv2 rootWMI rootMSPS rootdirectory rootPolicy rootvirtualization rootInterop rootHardware rootServiceModel rootSecurityCenter rootMicrosoft rootAppv rootdcim rootCIMV2mdm rootCIMV2Security rootCIMV2power rootCIMV2TerminalServices rootHyperVClusterv2 rootRSOPUser rootRSOPComputer rootStandardCimv2embedded rootdirectoryLDAP rootvirtualizationv2 rootMicrosoftHomeNet rootMicrosoftprotectionManagement rootMicrosoftWindows rootMicrosoftSecurityClient rootMicrosoftUev rootdcimsysman rootCIMV2mdmdmmap rootCIMV2SecurityMicrosoftTpm rootCIMV2SecurityMicrosoftVolumeEncryption rootMicrosoftWindowsRemoteAccess rootMicrosoftWindowsDns rootMicrosoftWindowsPowershellv3 rootMicrosoftWindowsHgs rootMicrosoftWindowsWindowsUpdate rootMicrosoftWindowsDeviceGuard rootMicrosoftWindowsTaskScheduler rootMicrosoftWindowsDesiredStateConfigurationProxy rootMicrosoftWindowsSmbWitness rootMicrosoftWindowsWdac rootMicrosoftWindowsStorageReplica rootMicrosoftWindowswinrm rootMicrosoftWindowsAppBackgroundTask rootMicrosoftWindowsDHCP rootMicrosoftWindowsPS_MMAgent rootMicrosoftWindowsStorage rootMicrosoftWindowsHardwareManagement rootMicrosoftWindowsSMB rootMicrosoftWindowsEventTracingManagement rootMicrosoftWindowsDesiredStateConfiguration rootMicrosoftWindowsAttestation rootMicrosoftWindowsCI rootMicrosoftWindowsdfsn rootMicrosoftWindowsDeliveryOptimization rootMicrosoftWindowsDefender rootdcimsysmanbiosattributes rootdcimsysmanwmisecurity rootMicrosoftWindowsRemoteAccessClient rootMicrosoftWindowsStoragePT rootMicrosoftWindowsStorageProviders_v2 rootMicrosoftWindowsStoragePTAlt
Once you know the names of namespaces, use the previous parts of this mini-series to query the WMI class names located in a given namespace. For example, the code below lists all WMI classes in the namespace ‘rootMicrosoftWindowsWindowsUpdate’:
$ns = 'rootMicrosoftWindowsWindowsUpdate' Get-CimClass -Namespace $ns | Select-Object -ExpandProperty CimClassName | Sort-Object
Class names that start with a double underscore are for internal purposes:
__AbsoluteTimerInstruction __ACE __AggregateEvent __ClassCreationEvent __ClassDeletionEvent __ClassModificationEvent __ClassOperationEvent __ClassProviderRegistration __ConsumerFailureEvent __Event __EventConsumer __EventConsumerProviderRegistration __EventDroppedEvent __EventFilter __EventGenerator __EventProviderRegistration __EventQueueOverflowEvent __ExtendedStatus __ExtrinsicEvent __FilterToConsumerBinding __IndicationRelated __InstanceCreationEvent __InstanceDeletionEvent __InstanceModificationEvent __InstanceOperationEvent __InstanceProviderRegistration __IntervalTimerInstruction __MethodInvocationEvent __MethodProviderRegistration __NAMESPACE __NamespaceCreationEvent __NamespaceDeletionEvent __NamespaceModificationEvent __NamespaceOperationEvent __NotifyStatus __NTLMUser9X __ObjectProviderRegistration __PARAMETERS __PropertyProviderRegistration __Provider __ProviderRegistration __QOSFailureEvent __SecurityDescriptor __SecurityRelatedClass __SystemClass __SystemEvent __SystemSecurity __thisNAMESPACE __TimerEvent __TimerInstruction __TimerNextFiring __Trustee __Win32Provider CIM_ClassCreation CIM_ClassDeletion CIM_ClassIndication CIM_ClassModification CIM_Error CIM_Indication CIM_InstCreation CIM_InstDeletion CIM_InstIndication CIM_InstModification MSFT_ExtendedStatus MSFT_WmiError MSFT_WUOperations MSFT_WUSettings MSFT_WUUpdate
To query the class MSFT_WUSettings in this namespace (if present on your machine), run this:
$ns = 'rootMicrosoftWindowsWindowsUpdate' Get-CimInstance -ClassName MSFT_WUSettings -Namespace $ns
The result is an exception which indicates that you may be up for surprises when exploring new and sparsely documented internal WMI classes. Depending on your operating system and license type, operations may or may not be supported. If they are not supported, you may end up with a “provider failure” exception.
In addition, some WMI classes (like the ones in this namespace) are not so much designed to contain properties and return information. Instead, they contain methods (commands), in this case to manage Windows Update:
$ns = 'rootMicrosoftWindowsWindowsUpdate' Get-CimClass -Namespace $ns -ClassName 'MSFT_WUOperations' | Select-Object -ExpandProperty CimClassMethods
The result shows the methods:
Name ReturnType Parameters Qualifiers ---- ---------- ---------- ---------- ScanForUpdates UInt32 {SearchCriteria, Updates} {implemented, static} InstallUpdates UInt32 {DownloadOnly, Updates, RebootRequired} {implemented, static}
Here is a practical example for Windows Server 2019 machines. The script remotely accesses the servers (in parallel) and uses local WMI to check for security updates, then installs them:
# list of names of Windows Server 2019 machines to update: $servers="Server2019-IIS","Server2019-AD" $ns = "root/Microsoft/Windows/WindowsUpdate" $class = "MSFT_WUOperations" Invoke-Command -ComputerName $servers -ScriptBlock { # find missing updates: $arg = @{SearchCriteria="IsInstalled=0 AND AutoSelectOnWebSites=1"} $r = Invoke-CimMethod -Namespace $ns -ClassName $class -MethodName ScanForUpdates -Arguments $arg # install missing updates: if ($r.Updates) { $arg = @{Updates=$r.Updates} Invoke-CimMethod -Namespace $ns -ClassName $class -MethodName InstallUpdates -Arguments $arg } }
Note that the code above works on Windows Server 2019 but fails on Windows Server 2016 (because WMI class names slightly changed). If you still would like to dig deeper, we can highly recommend https://github.com/microsoft/MSLab/blob/master/Scenarios/Windows%20Update/readme.md which is a rich set of examples on how to use WMI to manage Windows Updates on Windows Servers.
And if you’re interested in WMI in general, head over to https://powershell.one/wmi/commands for more information.