Deploy a custom compliance policy in MEM

Did you know that Microsoft Endpoint Manager recently released a feature in preview to use custom compliance settings for Windows 10 and later devices? You may have noticed the Scripts pane in your MEM console – it’s for custom compliance!

There are two steps to deploying a custom compliance policy. First, we need a JSON file that defines what we are checking. Then we need a PowerShell script that checks what was defined in the JSON file.

Create a JSON file for Custom Compliance

According to the Microsoft Docs, our JSON for custom compliance needs the following information listed:

  • SettingName
  • Operator
  • DataType
  • Operand
  • MoreInfoURL
  • RemediationStrings

There’s a lot more detail on the Docs, included supported data types and languages, but the easiest way I’ve found to get started is by copying the example JSON file and editing it to fit our needs. I’ll start by doing just that and copying the JSON contents from the Docs page into Visual Studio Code:

Visual Studio Code

For our test I think it’d be fun to check a device’s uptime. If a device hasn’t restarted for 30 days, for example, then we’ll mark it out of compliance and tell the user to reboot. (Note that in the real world, this isn’t super useful, because Windows Fast Startup doesn’t reset this number)

For our rule, we want the uptime to be less than 30 days, or else it will be out of compliance:

             "Title":"This device hasn't restarted in {ActualValue} days.",
             "Description": "Please reboot the device."
Custom Compliance JSON

Create the PowerShell script that checks for the JSON contents

Now that we know what the JSON is looking for, let’s make a simple script the corresponding contents. After some testing on the device to get PowerShell to return the uptime in days, I have:

$Time = Get-CIMInstance -Class CIM_OperatingSystem | Select-Object LastBootUpTime
$Today = get-date
$Difference = new-timespan -start $time.LastBootUpTime -end $Today
$Days = [int64] $Difference.Days
$hash = @{ Uptime = $Days; }
return $hash | ConvertTo-Json -Compress
PowerShell Uptime script

The script checks the last boot time reported in the OS, compares it against the current date, grabs the Days count from that comparison, casts the variable as an int64 (since that’s what the JSON is looking for), and then returns the content as a JSON value.

That last part I took from the sample also on the Microsoft Docs.

Create the custom compliance policy

Now that we have the JSON and PowerShell script, let’s create the custom policy. Start by uploading the script in Microsoft Endpoint Manager > Devices > Compliance policies > Scripts >+ Add

Upload Script

Provide a detailed name and description:


In the settings pane, paste the detection script into the window and edit the remaining settings. For our script we’ll want to run as system and in 64 bit PowerShell, so we will leave the options as default:

Script Settings

Then review and click create!

Create script

Now we need to actually create the custom compliance policy in Microsoft Endpoint Manager > Devices > Compliance policies > + Create policy

Create compliance policy

Provide a simple name and click next:


In compliance settings, change custom compliance to Require, and select the discovery script we just uploaded:

Discovery Script

And then upload the matching JSON file:

JSON File for custom compliance

And finally we’ll target to our test group and create the policy:

Beautiful! And now we need to wait for the device to report back, and we’ll see:

Device Compliance

The device is compliant! I did notice that devices will appear as “not applicable” until you reboot them, which does somewhat invalidate the usefulness of this custom compliance script. But hey, that’s just an example use! Be on the lookout though – as this feature comes out of preview, it may require an additional license (as stated in the purple banner when configure it), which would result in devices maybe not being applicable.

Happy monitoring 🎯

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *