Windows 10 MDM Bridge WMI Provider: Settings template

This week my post is a few days later, as my post is an extension of my session at the Workplace Ninja Virtual Summit 2020. At the virtual summit I did a session about Getting to know the Windows 10 MDM WMI Bridge provider and during my session I shared how to easily work with the Windows 10 MDM Bridge WMI provider. Similar to using Microsoft Intune to address the different CSPs, we can also use PowerShell via the WMI bridge.

The main thing that I’ve showed at the end of that session was a setting template, basically a PowerShell-function, that can be used to set, adjust and remove nearly all settings via the MDM WMI Bridge provider. That PowerShell-script is available below and I’ve completely documented the use, parameters and what it exactly does.

function Update-PolicySetting {
<#
.SYNOPSIS
A simple function to update policy settings by using MDM WMI Bridge
.DESCRIPTION
This function provides the capability to adjust policy settings by using the MDM WMI Bridge.
It supports the capabilities to create, update and remove an instance
.PARAMETER className
This parameter is required for the name of the WMI class
.PARAMETER parentID
This parameter is required for the name of the parent node of the OMA-URI
.PARAMETER instanceID
This parameter is required for the name of the WMI instance, which is the node of the OMA-URI
.PARAMETER configureProperty
This parameter is required when configuring a setting and is the name of the property
.PARAMETER valueProperty
This parameter is required when configuring a setting and is the value of the property
.PARAMETER removeInstance
This switch is used to indicate that the specified variables are used for deleting the WMI instance
.EXAMPLE
Update-PolicySetting -className 'MDM_Policy_Config01_Start02' -parentID './Vendor/MSFT/Policy/Config' -instanceID 'Start' -configureProperty 'HideAppList' -valueProperty 1
This example will run the function and configure a the property to hide the app list in Start
.EXAMPLE
Update-PolicySetting -className 'MDM_Policy_Config01_Start02' -parentID './Vendor/MSFT/Policy/Config' -instanceID 'Start' -removeInstance
This example will run the function and remove the instance of Start
.NOTES
Author: Peter van der Woude
Contact: pvanderwoude@hotmail.com
#>
param (
[Parameter(Mandatory=$true)]$className,
[Parameter(Mandatory=$true)]$parentID,
[Parameter(Mandatory=$true)]$instanceID,
[Parameter(Mandatory=$false)]$configureProperty,
[Parameter(Mandatory=$false)]$valueProperty,
[Parameter(Mandatory=$false)][Switch]$removeInstance
)
try {
#Get a specific instance
$instanceObject = Get-CimInstance -Namespace 'root\cimv2\mdm\dmmap' -ClassName $className -Filter "ParentID='$parentID' and InstanceID='$instanceID'" -ErrorAction Stop
}
catch {
Write-Host $_ | Out-String
}
#Verify the action
if ($removeInstance -eq $false) {
#Verify if the additional required parameters are provided
if ($PSBoundParameters.ContainsKey('configureProperty') -and ($PSBoundParameters.ContainsKey('valueProperty'))) {
#Verify if the instance already exists
if ($null -eq $instanceObject) {
try {
#Create a new instance
New-CimInstance -Namespace 'root\cimv2\mdm\dmmap' -ClassName $className -Property @{ InstanceID=$instanceID; ParentID=$parentID; $configureProperty=$valueProperty } -ErrorAction Stop
Write-Output "Successfully created the instance of '$instanceID'"
}
catch {
Write-Host $_ | Out-String
}
}
else {
try {
#Adjust a specific property
$instanceObject.$configureProperty = $valueProperty
#Modify an existing instance
Set-CimInstance -CimInstance $instanceObject -ErrorAction Stop
Write-Output "Successfully adjusted the instance of '$instanceID'"
}
catch {
Write-Host $_ | Out-String
}
}
}
else {
Write-Output ">> Make sure to provide a value for configureProperty and valueProperty when creating or adjusting an instance <<"
}
}
elseif ($removeInstance -eq $true) {
#Verify if the instance already exists
if ($null -ne $instanceObject) {
try {
#Remove a specific instance
Remove-CimInstance -InputObject $instanceObject -ErrorAction Stop
Write-Output "Successfully removed the instance of '$instanceID'"
}
catch {
Write-Host $_ | Out-String
}
}
else {
Write-Output "No instance available of '$instanceID'"
}
}
}

An example to use this function to hide the app list in Start can be found below.

Update-PolicySetting -className 'MDM_Policy_Config01_Start02' -parentID './Vendor/MSFT/Policy/Config' -instanceID 'Start' -configureProperty 'HideAppList' -valueProperty 1 

As mentioned during my session, the required parameters can be found mainly by looking at WMI by using the WMI Explorer. The name of the instance is the node of the OMA-URI that contains the required configuration. In this case Start. When you can’t find the required information, you can always refer to the documentation that’s shared below.

More information

During my sessions I’ve showed many reference to post that describe the subjects that I covered. For future reference those posts are summarized below.

Windows 10 MDM (PowerShell) scripting

A long, long time ago, I wrote about the MDM WMI Bridge provider. Nowadays I notice that the MDM WMI Bridge provider is still an unknown configuration layer for many IT admins. That’s why I’ve decided to do another post about the MDM WMI Bridge provider. A quick reminder: the MDM WMI Bridge provider is used to map the CSPs to WMI. This time my post is more focused on providing some examples and guidance. Besides that it’s also a nice addition on my latest posts about Windows 10 MDM configurations, policy refresh and troubleshooting. I’ll start this post by showing how to configure device settings and I’ll end this post by showing how to trigger device actions.

Keep in mind that this post is about configuring device settings. That means that every action requires to run in SYSTEM context. I advise to use PsExec for executing the scripts and tools mentioned in this post

Configuring device settings

The easiest starting point for everything related to WMI is Windows Management Instrumentation Tester (in short wbemtest). As an example I’ll take last weeks post to another level by also looking at the Reboot CSP for this post. The starting point for that is the MDM_Reboot_Schedule01 class.

Let’s start at the beginning. The root\cimv2\mdm\dmmap namespace, is the namespace that contains all the information regarding MDM in WMI. This is the MDM WMI Bridge provider. This namespace contains the WMI classes that map to CSP nodes. There are 3 methods available to get the available WMI classes:

  1. The docs about the MDM Bridge WMI provider
  2. Use wbemtest to connect to the namespace and click Enum Classes
  3. User PowerShell (Get-CIMClass) to enumerate the available classes

For this example I’ll use wbemtest to connect to the root\cimv2\mdm\dmmap namespace and to enumerate the available classes. This tool is an easy method for showing information via a UI. When knowing the exact class, it’s also possible to directly connect to that class by using Open Class instead of Enum Classes.

In this example, I know the class, which enables me to open the specific MDM_Reboot_Schedule01 class. Connecting to that class, provides me with the available properties (DailyRecurrent, InstanceID, ParentID, Single). These properties are well documented in the earlier mentioned article. In some scenarios, the classes and/or properties are not yet documented. In those scenarios wbemtest can be a very good starting point for getting the required information.

Now the available classes and properties are known, it’s time to have a look at the available options. As it’s basically standard WMI, at this point, there are also the standard WMI PowerShell scripting options available (Get, New, Remove and Modify). Below are some basic examples of using the CimCmdlets for WMI. Having mentioned that, I also deliberately left out some real New-CimInstance and Remove-CimInstance examples, as the example that I use for this post doesn’t support those actions. The MDM_Reboot_Schedule01 class already contains an instance and can’t contain multiple instances. Below are some generic example of using those cmdlets.

#Enumerate available instances
Get-CimInstance -Namespace $namespaceName -ClassName $className
#Create a new instance
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{}
#Get a specific instance 
$instanceObject = Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID='$parentID' and InstanceID='$instanceID'"

#Remove a specific instance
Remove-CimInstance -CimInstance $instanceObject

That basically means that it’s only possible to modify the available instance in the MDM_Reboot_Schedule01 class. That instance is Schedule. The Schedule instance can be adjusted by adding a value to the Single property and/ or the DailyRecurrent property. Those properties are used to actually create the specified schedule. Just like in the CSP configuration, the date and time value is ISO8601 and in UTC. The example below will get the Schedule instance in the root\cimv2\mdm\dmmap namespace, and will modify the Single property to configure a new single scheduled reboot.

#Declare variables
$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_Reboot_Schedule01"
$parentID = "./Vendor/MSFT/Reboot"
$instanceID = "Schedule"
$singleSchedule = "2019-10-01T22:00:00Z"

#Get a specific instance
$instanceObject = Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID='$parentID' and InstanceID='$instanceID'"

#Adjust a specific property
$instanceObject.Single = $singleSchedule

#Modify an existing instance
Set-CimInstance -CimInstance $instanceObject

Triggering device actions

Besides configuring settings via the MDM WMI Bridge provider, it’s also possible to trigger actions via the provider. When still looking at the Reboot CSP, that CSP also contains a node to execute RebootNow. RebootNow will trigger a reboot within 5 minutes. That action is available within the Intune console as a Restart action for a device. The nice thing is that this action can also be triggered via the MDM WMI Bridge provider.

Let’s skip the beginning about connecting to the WMI namespace and directly navigate to the required WMI class. The MDM_Reboot class. When connecting to the MDM_Reboot class, by using wbemtest, it’s immediately clear why wbemtest is such a nice and easy tool. After connecting to the class, wbemtest immediately provides an overview of the available methods. In this case the RebootNowMethod method.

Triggering the RebootNowMethod method, via PowerShell, will provide an alternative (and very creative) method for rebooting a device. This method is well documented in the earlier mentioned documentation. In some scenarios, the methods are not yet documented. In those scenarios wbemtest can be a very good starting point for getting the required information.

The RebootNowMethod method can be triggered by getting the available instance of the MDM_Reboot class. That instance is Reboot. That instance can be used to trigger the RebootNowMethod method. The example below will get the Reboot instance in the root\cimv2\mdm\dmmap namespace, and will trigger the RebootNowMethod method to trigger a reboot within five minutes.

#Declare variables
$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_Reboot"
$parentID = "./Vendor/MSFT/Reboot"
$instanceID = "Reboot"
$methodName = "RebootNowMethod"

#Get a specific instance
$instanceObject = Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID='$parentID' and InstanceID='$instanceID'"

#Trigger specific method
Invoke-CimMethod -InputObject $instanceObject -MethodName $methodName

Now let’s end this post by having a look at the effect of triggering the RebootNowMethod method. Below is an example of a simplified version (read: a one-liner) of the previous script. Just for demo purposes. After triggering that the RebootNowMethod method, the device will immediately provide a popup with a reboot notification.

More information

For more information about PowerShell and the MDM WMI Bridge provider, have a look at this article about Using PowerShell scripting with the WMI Bridge Provider.