Skip to content
View in the app

A better way to browse. Learn more.

Learn more

Intune Remediations for config drift, and the one that never fixed anything

Featured Replies

Every environment has little problems that keep coming back, like a service that keeps getting disabled or a registry setting an app keeps resetting. Each time, somebody calls the help desk and a tech fixes it by hand. Intune Remediations (previously Proactive Remediations) are how we stop doing that. You give Intune a pair of PowerShell scripts that run on a schedule, one to detect the problem and one to fix it. Below is how we write them, how we schedule and check them, and the Graph gotcha that left one of ours detecting problems for weeks without fixing a single one.

Licensing and setup

  • Licensing that includes Remediations, which means Windows Enterprise E3/E5 or Education A3/A5 (often through Microsoft 365 E3/E5 or A3/A5), or Windows VDA per user.
  • Devices that are Entra joined or hybrid joined and managed by Intune. The Intune Management Extension is what runs the scripts.
  • A test device group.

How the two scripts work together

The detection script runs first. exit 0 means everything's fine and there's nothing to do. exit 1 means it found an issue, and Intune runs the remediation script.

The remediation script does the fix. After it runs, the detection script runs again so Intune can report whether the fix held.

Whatever the scripts write to STDOUT shows up as the detection and remediation output in the portal, and the last line is what you see in reports. Make that line useful to whoever reads the report later, because "ok" doesn't tell them much.

The detection script

This example makes sure the Windows Time service is set to automatic and running.

# Detect-W32Time.ps1
try {
    $svc = Get-Service -Name W32Time -ErrorAction Stop
    if ($svc.StartType -ne 'Automatic' -or $svc.Status -ne 'Running') {
        Write-Output "Issue: W32Time StartType=$($svc.StartType) Status=$($svc.Status)"
        exit 1
    }
    Write-Output "OK: W32Time running"
    exit 0
}
catch {
    Write-Output "Issue: $($_.Exception.Message)"
    exit 1
}

The remediation script

# Remediate-W32Time.ps1
try {
    Set-Service -Name W32Time -StartupType Automatic -ErrorAction Stop
    Start-Service -Name W32Time -ErrorAction Stop
    w32tm /resync /force | Out-Null
    Write-Output "Remediated: W32Time set to Automatic and started"
    exit 0
}
catch {
    Write-Output "Remediation failed: $($_.Exception.Message)"
    exit 1
}

Keep both scripts idempotent, so running the fix twice does no harm. Save them as UTF-8, and keep them small and dependency-free. There's no guarantee any module you rely on exists on the client.

Creating the package

In the Intune admin center, go to Devices, then Scripts and remediations, then Remediations, and create a script package. Upload both scripts and pick the settings.

  • "Run this script using the logged-on credentials" should be No (so it runs as SYSTEM) for machine settings like services. Only use Yes for per-user fixes.
  • Only turn on "Enforce script signature check" if you sign your scripts.
  • Set "Run script in 64-bit PowerShell" to Yes for most things, so you see the real registry and System32.

Assigning and scheduling

Assign it to a pilot group first and choose a schedule of once, hourly or daily (with a time). Daily is a sensible default for drift. Hourly is for things that genuinely need it, since every run is another process on every device. You can also run it on a single device on demand from that device's page with the "Run remediation" action, which is handy for testing.

Checking that it works

Open the remediation and go to the device status view. Add the output columns (pre-remediation detection output, remediation output and post-remediation detection output) so you can see what each script reported. A working package shows devices moving from "With issues" to "Issues fixed." On the device itself, the Intune Management Extension logs under C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\ show each run.

Then break it on purpose. Stop the service on a test device, trigger the remediation on demand, and make sure the service comes back.

The package that only ever detected

We automate a lot of Intune through Microsoft Graph, including creating and assigning remediation packages across tenants. One package showed exactly the right detection results. Devices were listed "with issues," and the output clearly explained the problem. And yet nothing ever got fixed. Weeks later, the same devices were still on the list.

The assignment had been created through Graph with the flag that tells Intune to run the remediation script set to true. When we read it back in the portal, the package was assigned in a detection-only state. In our experience that flag on the assignment can be silently ignored. The API call succeeds, no error comes back, and the package runs detection only.

Here's what we do now.

  1. After any create or assign through Graph, open the package in the portal and read back the assignment. Make sure the remediation script is enabled to run, not just detection.
  2. If it isn't, fix it in the portal (or re-check your Graph payload against the current API documentation) and read it back again.
  3. Before calling the rollout done, wait until at least one device shows "Issues fixed" in the report. If all you ever see is "With issues," the remediation side isn't running.

Other ways these go sideways

  • If detection exits 0 when there's a problem, for example because an error got swallowed, the remediation never runs. Always exit 1 in the catch block.
  • The post-remediation detection runs right away. If your fix only takes effect after a reboot or a service restart, detection reports "failed" even though it worked. Account for that in the logic or the output.
  • Keep scripts and output short. Long output gets truncated in the report.
  • Scripts set to run as the logged-on user fail when nobody is logged on, and they can't change machine settings.

I've stopped trusting any automated assignment until I've seen "Issues fixed" in the report myself. It costs a day of waiting, which beats finding out weeks later.

Create an account or sign in to comment

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.