Intune Proactive Remediations: PowerShell Script Library and Patterns · CloudEngineerHub
PowerShell11 min read8 views
Intune Proactive Remediations: PowerShell Script Library and Patterns
Build a Proactive Remediations library for Intune: detection and remediation script patterns, exit codes, scheduling, reporting via Graph, and troubleshooting IME logs.
C
CloudEngineerHub Team
Published: August 26, 2026· Last Updated: October 15, 2026·11 min read
Intune Proactive Remediations: PowerShell Script Library and Patterns
Proactive remediations — formerly device health scripts — are Intune's self-healing engine: a detection script runs on schedule, and when it reports a problem, a matching remediation script fixes it, both without a ticket ever being filed. The difference between a chaotic remediation catalog and a professional one is a small set of patterns: correct exit codes, honest output, idempotent fixes, and reporting you can actually read. This article gives you the patterns and a starter library.
Visual Walkthrough
Every reliable detection script follows this exact structure — copy it.
Decision TreeDetection Script Anatomy — The Exit-Code Contract5/5
Decision gate
Is the state healthy?
One question, one exit code — keep detection dumb and honest.
Healthy → exit 0
1
Test the condition
Single cmdlet or property read; no side effects, no output noise.
2
Exit 0, no output
Silence is the success contract — Intune treats it as compliant.
Unhealthy → exit 1
1
Emit one evidence line
Write the observed value — your future self reads the report.
2
Exit 1
Signals "needs remediation"; the paired fix script may now run.
3
Remediate idempotently
Fix script is safe to run repeatedly; no reboots without consent.
4
Exit 0 after fix
Next detection run proves remediation worked.
Detection Script Anatomy — The Exit-Code Contract. Gate: Is the state healthy? — Healthy → exit 0: Test the condition — Healthy → exit 0: Exit 0, no output — Unhealthy → exit 1: Emit one evidence line — Unhealthy → exit 1: Exit 1 — Unhealthy → exit 1: Remediate idempotently — Unhealthy → exit 1: Exit 0 after fix
C
CloudEngineerHub Team
Author
The CloudEngineerHub editorial team — Microsoft endpoint management and cloud engineers writing hands-on guides on Intune, Azure, Entra ID, Autopilot, Defender and PowerShell. Every article is reviewed against current Microsoft documentation.
Devices enrolled in Intune with the Microsoft Intune Management Extension service (IME) — automatic on Windows 10/11 enrolled devices that have a user enrolled or a device licensed for Intune.
Windows 10 version 1903 or later for remediations.
Intune Administrator role to create and assign script packages in intune.microsoft.com.
PowerShell 5.1 (the client-side execution engine) — avoid syntax newer than 5.1 in shipped scripts.
Permissions for Graph reporting: DeviceManagementConfiguration.Read.All to read deviceHealthScripts.
How It Works
A remediation package is two scripts bound together: a detection script and a remediation script. Intune runs detection on the schedule you choose (hourly, daily, weekly, or once). The exit code decides everything:
Exit 0 from detection means no issue detected — the device is compliant and nothing else runs.
Exit 1 (or any non-zero, non-success value) means issue detected — Intune runs the remediation script on that device.
The remediation script should exit 0 when the fix succeeded. Any other exit code marks the run as failed for that device.
Write-Output lines from both scripts are captured and shown in the reporting view, so print exactly one short, human-readable line — the service retains only limited output. Detection and remediation run in the context you select (system or signed-in user), and you can force 64-bit PowerShell, which matters when you touch Program Files or registry views.
Step-by-Step Implementation
1. Pick your first target
Choose something safe, boring, and visible: a service startup type, a registry setting your applications depend on, or a log-directory cleanup. Avoid anything destructive for pilot one.
2. Write detection that is pure and silent
Detection should only observe. No Set-*, no Start-Service, no side effects. Print one line describing the state when an issue is found.
3. Write remediation that is idempotent
Remediation runs only after detection says something is wrong, but network retries and overlapping schedules make double-runs possible. Every fix must be safe to apply twice.
4. Create the package
In intune.microsoft.com go to Devices > Remediations, create the package, upload both scripts, choose context (system), enable 64-bit PowerShell, and set the schedule. Assign to a pilot ring first.
5. Read the results
Devices > Remediations > your package shows per-device status and the captured output. For automation, the Graph side is deviceHealthScripts and its deviceRunStates.
Configuration Deep Dive
Context and bitness. System context runs under the machine account — right for services, registry under HKLM, and file-system fixes. User context is for per-user settings. Enable "Run script in 64 bit PowerShell" or you will silently see the 32-bit view of the filesystem and WOW6432Node registry.
Schedules. Hourly for fragile settings, daily for most hygiene, weekly for slow-drift items, Once for one-time campaigns. Every schedule is a trade between drift-detection latency and client load — a fleet-wide hourly remediation is a self-inflicted DDoS on your management point budget.
Output discipline. Print exactly one line, usually the observed problem or the fix applied: "Issue: WinRM service disabled", "Remediated: WinRM startup type set to Automatic". Those lines are what help desk reads when they triage the report.
Size and hygiene. Keep scripts small and self-contained; the service enforces size limits and rejects oversized packages. No interactive prompts, no Write-Host (use Write-Output), no unsigned modules from the internet, and honor the "enforce script signature check" toggle if your organization requires signing.
Real-World Enterprise Scenario
A healthcare provider with 4,300 endpoints kept losing print spooler health after driver rotations, and WinRM had drifted off on a third of the fleet, silently breaking their remote-support tooling. Two remediation packages — the service-recovery pattern below for WinRM and a spooler variant — replaced a manual checklist that service desk ran weekly. Within a month, remediation reports showed WinRM drift being fixed on 60-90 devices per day, remote support failure tickets dropped to near zero, and the team standardized on the same detection/remediation skeleton for every new package in the library.
PowerShell for Proactive Remediations
Script 1 — detection: fail with a clear message when a service is misconfigured:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Detection: exit 0 = healthy, non-zero = issue detected$service = Get-Service -Name WinRM -ErrorAction SilentlyContinue
$startup = (Get-CimInstance -ClassName Win32_Service -Filter"Name='WinRM'").StartMode
if (-not $service) {
Write-Output 'Issue: WinRM service is missing'
exit 1
}
if ($startup -ne'Auto') {
Write-Output ('Issue: WinRM startup type is ' + $startup + ' (expected Auto)')
exit 1
}
if ($service.Status -ne'Running') {
Write-Output 'Issue: WinRM service is not running'
exit 1
}
Write-Output 'No issue detected: WinRM healthy'
exit 0# Expected output (unhealthy device):# Issue: WinRM startup type is Manual (expected Auto)
Script 2 — remediation: fix, verify, and report honestly:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Remediation: apply the fix, verify it, exit 0 only on verified successtry {
Set-Service -Name WinRM -StartupType Automatic
Start-Service -Name WinRM -ErrorAction Stop
# Verify rather than assume - this is what makes remediations trustworthy$check = Get-CimInstance -ClassName Win32_Service -Filter"Name='WinRM'"if ($check.StartMode -eq'Auto' -and$check.State -eq'Running') {
Write-Output 'Remediated: WinRM set to Automatic and running'
exit 0
}
Write-Output ('Failed: verification shows StartMode=' + $check.StartMode + ' State=' + $check.State)
exit 1
}
catch {
Write-Output ('Failed with exception: ' + $_.Exception.Message)
exit 1
}
# Expected output (after fix):# Remediated: WinRM set to Automatic and running
Script 3 — report remediation package health across the tenant via Graph:
Exit 1 flips the device into the remediation queue for this package.
remediate
3
Remediation executes
Fix script runs silently as SYSTEM with a 5-minute budget.
verify
4
Re-run detection
The same detection script must now exit 0 — proof, not hope.
telemetry
5
Results report
Per-device outcome lands in Reports → Remediations for trend analysis.
6
Repeat on schedule
The loop continues — drift gets caught the day it appears.
Continuous cycle
Proactive Remediations — The Detect → Fix → Verify Loop. 1. Detection script runs: Scheduled (daily/hourly): exit 0 healthy, exit 1 unhealthy — nothing more. — 2. Verdict: unhealthy: Exit 1 flips the device into the remediation queue for this package. — 3. Remediation executes: Fix script runs silently as SYSTEM with a 5-minute budget. — 4. Re-run detection: The same detection script must now exit 0 — proof, not hope. — 5. Results report: Per-device outcome lands in Reports → Remediations for trend analysis. — 6. Repeat on schedule: The loop continues — drift gets caught the day it appears.
Common Errors
exit 1 in detection treated as script failure, not issue detection. It is actually correct behavior — non-zero from detection means "issue detected", which triggers remediation.
Using Write-Host. The pipeline captures standard output; Write-Host bypasses it in 5.1, so your evidence disappears.
Set-Service on a protected service. Some services are protected by the OS or policy; catch the exception and report honestly rather than letting the script die unhandled.
Assuming 64-bit. Filesystem redirection silently rewrites C:\Program Files to C:\Program Files (x86); always enable 64-bit execution for machine-scoped checks.
Hardcoded paths with single backslashes pasted from docs. Test on a clean device — path typos are the most common reason remediations "succeed" without changing anything.
Best Practices
Ship one fix per package; composite remediations are impossible to report on and hard to assign.
Name packages by outcome: "WinRM Service Recovery", not "Script12-fix".
Pilot every package against a ring group for at least one full schedule cycle before broad assignment.
Keep a catalog: package name, purpose, owner, schedule, and expected output line, reviewed quarterly.
Prefer CIM/GPO-backed settings over hand-rolled registry writes when a supported configuration profile exists — remediations are for the long tail, not a second configuration engine.
Version your scripts in Git and upload from the repo, so what runs in production is what was reviewed.
Security Considerations
Remediation scripts run as SYSTEM on every assigned device — a hostile or careless script is local-admin-grade code on your fleet.
Enable script signature enforcement where policy allows, and keep an approval step between merge and upload.
Store scripts in a controlled repository with code review; never upload scripts edited directly in the portal as the source of truth.
Audit the Remediations assignment list regularly; orphaned packages assigned to broad groups are both a security and a performance liability.
Output lines are visible to anyone with Intune read access — avoid printing secrets, tokens, or full file contents.
FAQ
Q: Do remediations require a special license?
A: Remediations are available with Intune licensing for enrolled Windows devices; confirm current entitlement details for your specific plan on the Microsoft Learn remediations page before planning large deployments.
Q: How long can my scripts be?
A: Keep them lean — the service enforces size limits and will reject oversized packages. If you need hundreds of lines, you probably need an app or a configuration baseline, not a remediation.
Q: Can remediations run on macOS?
A: No. Proactive remediations are Windows-only; macOS uses shell scripts with their own schedule model.
Q: Why does detection run but remediation never fires?
A: Detection exited 0, which means "no issue detected". Check your exit-code logic and the output column — the report tells you exactly what detection decided.
Q: Can I get remediation results into Power BI or a SIEM?
A: Yes, via the deviceHealthScripts Graph endpoints shown in script 3, or by exporting the report from the admin center; schedule a Graph pull and ship the CSV or JSON wherever your teams look.
Conclusion
Proactive remediations are the highest-leverage automation in Intune once you treat them as a curated library rather than a script dump. Fix one boring problem this week with the detection/remediation skeleton above, read the report, and you will never look at recurring-ticket hygiene issues the same way again.
Comments
0No comments yet — be the first to share your thoughts.