Detect Intune IME Service Failures with PowerShell · CloudEngineerHub
Detection & Remediation9 min read4 views
Detecting Intune Management Extension Service Failures with PowerShell
Spot Intune Management Extension crash loops before they corrupt app deployments, using service state, System event log crash counts, and IME log scans.
C
CloudEngineerHub Team
Published: September 10, 2026· Last Updated: September 28, 2026·9 min read
A service that starts, crashes, and starts again is harder to catch than a service that simply stops. The Intune Management Extension is supervised by Service Control Manager, which restarts it after unexpected failures, so from the admin center the device can look completely normal: it checks in, it syncs, it reports. Meanwhile every Win32 app install, remediation script, and platform script on that device is a coin flip, because the agent process can die in the middle of an operation. Users see apps that never arrive, and you see deployment progress bars that stall or reset for no obvious reason.
Visual Walkthrough
The engine behind every “Detect with PowerShell” runbook on this site.
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.
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.
This post gives you a detection and remediation pair that runs on the device itself. Detection reads the service status and start type, counts genuine crash events from the System event log, and scans the agent's own log for recent error activity. Remediation does only what is provably safe: enable and start the service, and when the crash evidence is strong, perform a single controlled restart - never while an install is running.
Symptoms
Crash-looping agents rarely announce themselves through a single clean error. The signals are indirect and easy to misread:
Win32 app installs on specific devices fail intermittently and succeed on retry, with no consistent exit code to point at.
Remediation packages flip between "Error" and "Remediated" on the same device across runs.
The System event log shows "The Microsoft Intune Management Extension service terminated unexpectedly" - event ID 7031 or 7034 from Service Control Manager - repeating over hours or days.
The IME log under C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\ ends abruptly mid-operation rather than at a natural completion point.
services.msc usually shows the service as Running even during a crash loop, because Service Control Manager keeps restarting it.
That last point is why a quick "is the service running?" check tells you almost nothing. You need the event history, not just the current status.
Possible Causes
A damaged agent installation
Interrupted agent upgrades, disk exhaustion during an update, or antivirus quarantining agent binaries can leave the service registered with half-written files. The service starts, faults on a missing or corrupt module, and the cycle repeats until the cause is fixed.
Security software interfering with the agent process
Endpoint protection that injects into, blocks, or terminates unsigned or unrecognized service processes can take the IME down repeatedly. The pattern is recognizable because the crash events cluster around the same time security scans run.
Corrupted local agent state
The agent caches evaluation and app state locally. When that state becomes inconsistent after an aborted install or a power loss, the agent can fault during every evaluation attempt, producing a steady crash rhythm.
Broken platform dependencies
The IME depends on Windows platform components and .NET Framework runtime pieces. A failed patch cycle, a partially removed framework, or system file corruption can crash the agent at each startup before it writes anything useful to its log.
Deliberate interference from tooling
Hardening scripts, "debloat" utilities, or a cleanup job that kills processes it does not recognize can terminate the agent on a schedule. The crash events then line up with the tool's execution window, which is the clue that points away from the agent itself.
Detection Script
The detection below is read-only and safe to run at any frequency. It completes in a few seconds in 64-bit SYSTEM context and evaluates, in order: service presence, start type, running state, Service Control Manager crash events within a 24-hour lookback window, and an error scan of the IME log tail. All three knobs - lookback hours, crash threshold, and log tail depth - are parameters with sensible defaults.
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#Requires -RunAsAdministrator
[CmdletBinding()]
param(
[int] $LookbackHours = 24,
[int] $CrashLoopThreshold = 2,
[int] $LogTailLines = 400
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
<#
.SYNOPSIS
Detection script: looks for Intune Management Extension (IME) service
failure patterns - a disabled or stopped service, repeated unexpected
terminations recorded by Service Control Manager, and recent error
activity in the agent's own log.
.NOTES
Intended for Intune Scripts and Remediations, 64-bit SYSTEM context.
This script NEVER changes the system.
Exit 0 = service healthy (or a single, already-recovered crash),
1 = service disabled, stopped, or crash-looping,
2 = IME not installed (an assignment problem, not a service failure),
3 = unexpected error.
#>$logDir = 'C:\ProgramData\Company\Logs'$logFile = Join-Path $logDir'ImeServiceFailureDetection.log'$serviceName = 'IntuneManagementExtension'$serviceDisplayName = 'Microsoft Intune Management Extension'$imeLogPath = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.log'function Write-DetectionLog {
param([Parameter(Mandatory)][string] $Level, [Parameter(Mandatory)][string] $Message)
if (-not (Test-Path $logDir)) { New-Item -Path$logDir -ItemType Directory -Force | Out-Null }
"$([DateTime]::UtcNow.ToString('o')) [$Level] $Message" | Out-File -FilePath$logFile -Append -Encoding utf8
}
function Get-ScmCrashCount {
# Service Control Manager events 7031 and 7034 both record a service that # terminated unexpectedly. Their message text names the service's display # name, so both spellings are matched before an event is counted.param([Parameter(Mandatory)][datetime] $Since)
$scmQuery = @{
LogName = 'System'
ProviderName = 'Service Control Manager'
Id = @(7031, 7034)
StartTime = $Since
}
$events = @(Get-WinEvent -FilterHashtable$scmQuery -ErrorAction SilentlyContinue)
if ($events.Count -eq0) { return0 }
$pattern = '(' + [regex]::Escape($serviceDisplayName) + ')|(' + [regex]::Escape($serviceName) + ')'$crashEvents = @($events | Where-Object { $_.Message -and ($_.Message -match$pattern) })
return$crashEvents.Count
}
function Get-ImeLogErrorCount {
# Weak signal only: counts lines in the IME log tail that carry # error-style wording. Line timestamp formats differ between agent # builds, so recency is judged by the file's LastWriteTime rather than # by parsing individual lines.param([Parameter(Mandatory)][int] $TailLines)
if (-not (Test-Path $imeLogPath)) { return -1 }
try {
$tail = @(Get-Content -Path$imeLogPath -Tail$TailLines -ErrorAction Stop)
}
catch {
return -1
}
$errorPattern = '(?i)\berror\b|\bfailed\b|\bfatal\b'$hits = @($tail | Where-Object { $_ -match$errorPattern })
return$hits.Count
}
try {
Write-DetectionLog 'INFO''IME service failure detection run started.'$since = (Get-Date).AddHours(-1 * $LookbackHours)
# ---- Check 1: is the IME installed at all? ----$service = Get-Service -Name$serviceName -ErrorAction SilentlyContinue
if ($null -eq$service) {
Write-DetectionLog 'WARN'"Service '$serviceName' not found - IME is not installed. Installation is triggered by an Intune assignment, so this is not a service failure."
exit 2
}
$startMode = (Get-CimInstance -ClassName Win32_Service -Filter"Name='$serviceName'").StartMode
Write-DetectionLog 'INFO'"Service found. Status=$($service.Status) StartMode=$startMode" # ---- Check 2: start mode ----if ($startMode -eq'Disabled') {
Write-DetectionLog 'ERROR''IME service start type is Disabled - the agent cannot start and cannot recover on its own.'
exit 1
}
# ---- Check 3: running state ----if ($service.Status -ne'Running') {
Write-DetectionLog 'ERROR'"IME service is $($service.Status) (expected Running)."
exit 1
}
# ---- Check 4: unexpected terminations inside the lookback window ----$crashCount = Get-ScmCrashCount -Since$since
Write-DetectionLog 'INFO'"Service Control Manager events 7031/7034 naming the IME in the last $LookbackHours hour(s): $crashCount" # ---- Check 5: error-style lines in the IME log tail (weak signal) ----$logErrorCount = Get-ImeLogErrorCount -TailLines$LogTailLinesif ($logErrorCount -lt0) {
Write-DetectionLog 'WARN'"IME log not readable at $imeLogPath - log error scan skipped."
}
else {
Write-DetectionLog 'INFO'"IME log tail ($LogTailLines lines) contains $logErrorCount line(s) with error indicators."
}
if ($crashCount -ge$CrashLoopThreshold) {
Write-DetectionLog 'ERROR'"Crash-loop pattern: $crashCount unexpected termination(s) within $LookbackHours hour(s), threshold is $CrashLoopThreshold."
exit 1
}
if ($crashCount -eq1) {
Write-DetectionLog 'WARN''One unexpected termination recorded and the service is currently running - monitoring, not flagging.'
}
Write-DetectionLog 'INFO''IME service healthy by all available signals.'
exit 0
}
catch {
Write-DetectionLog 'ERROR'"Unexpected failure: $($_.Exception.Message)"
exit 3
}
finally {
Write-DetectionLog 'INFO''IME service failure detection run ended.'
}
Detection Logic
The checks move from "does it exist" to "how has it behaved", because each one only means something after the previous one passed.
Service presence.Get-Service -Name IntuneManagementExtension answers whether the agent is installed. If it is missing, this is not a service failure - Intune delivers the agent through assignments, so the script exits 2 and leaves the problem to the missing-IME workflow.
Start type. A CIM query against Win32_Service reads StartMode. Disabled is an immediate fail regardless of current status, because even a running service will not survive the next reboot.
Running state.Status must be Running. Stopped or start-pending states fail detection and hand a clean case to remediation.
Crash history. The script queries the System event log for provider Service Control Manager, event IDs 7031 and 7034 - both record "service terminated unexpectedly" - within the lookback window, then filters messages for the service's display name and short name. Two or more crashes inside 24 hours is the crash-loop signal and fails detection. A single crash with the service now stable produces a warning but not a failure, because one unexpected termination after an upgrade is common and self-recovering.
IME log scan. The last 400 lines of IntuneManagementExtension.log are scanned for error-style wording. This is deliberately labeled a weak signal in the code comments: log line formats vary between agent builds, so the script judges recency by the file's LastWriteTime and reports the count for your report view rather than failing the device on it alone.
A healthy result means: service installed, start type Automatic (or at least not Disabled), status Running, and no crash-loop pattern in the event window.
Remediation Script
The remediation is intentionally narrow: set the start type back to Automatic when it was disabled, start the service when it is not running, and - only when the event log shows repeated unexpected terminations - perform exactly one controlled restart. That restart is gated on AgentExecutor.exe not running, so an in-flight Win32 install is never torn down. It never reinstalls the agent and never deletes state.
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#Requires -RunAsAdministrator
[CmdletBinding()]
param(
[int] $LookbackHours = 24,
[int] $CrashLoopThreshold = 2
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
<#
.SYNOPSIS
Remediation script: recovers an Intune Management Extension (IME) service
that is disabled, stopped, or crash-looping.
.DESCRIPTION
Scope of this script (deliberately conservative):
- Sets the start type back to Automatic when the service is Disabled.
- Starts the service when it is not running.
- When the service is running but Service Control Manager recorded
repeated unexpected terminations, performs ONE controlled restart -
and only when no AgentExecutor.exe process is active, so an
in-flight Win32 install is never torn down.
- Never reinstalls the agent, never deletes agent state, never touches
user data.
#>$logDir = 'C:\ProgramData\Company\Logs'$logFile = Join-Path $logDir'ImeServiceFailureRemediation.log'$serviceName = 'IntuneManagementExtension'$serviceDisplayName = 'Microsoft Intune Management Extension'function Write-RemediationLog {
param([Parameter(Mandatory)][string] $Level, [Parameter(Mandatory)][string] $Message)
if (-not (Test-Path $logDir)) { New-Item -Path$logDir -ItemType Directory -Force | Out-Null }
"$([DateTime]::UtcNow.ToString('o')) [$Level] $Message" | Out-File -FilePath$logFile -Append -Encoding utf8
}
function Get-ScmCrashCount {
# Same query as the detection script: System log, Service Control Manager # provider, events 7031 and 7034, filtered to the IME service name.param([Parameter(Mandatory)][datetime] $Since)
$scmQuery = @{
LogName = 'System'
ProviderName = 'Service Control Manager'
Id = @(7031, 7034)
StartTime = $Since
}
$events = @(Get-WinEvent -FilterHashtable$scmQuery -ErrorAction SilentlyContinue)
if ($events.Count -eq0) { return0 }
$pattern = '(' + [regex]::Escape($serviceDisplayName) + ')|(' + [regex]::Escape($serviceName) + ')'$crashEvents = @($events | Where-Object { $_.Message -and ($_.Message -match$pattern) })
return$crashEvents.Count
}
try {
Write-RemediationLog 'INFO''IME service failure remediation run started.'$changed = $false$restarted = $false$service = Get-Service -Name$serviceName -ErrorAction SilentlyContinue
if ($null -eq$service) {
Write-RemediationLog 'WARN'"Service '$serviceName' not found - IME is not installed. Assigning any Win32 app or required system script triggers installation; no local repair applies."
exit 2
}
# ---- Enable the service when it is Disabled ----$startMode = (Get-CimInstance -ClassName Win32_Service -Filter"Name='$serviceName'").StartMode
if ($startMode -eq'Disabled') {
Set-Service -Name$serviceName -StartupType Automatic
Write-RemediationLog 'INFO''IME service was Disabled - startup type set to Automatic.'$changed = $true
}
# ---- Start the service when it is not running ----$service.Refresh()
if ($service.Status -ne'Running') {
Write-RemediationLog 'INFO'"Starting IME service (previous status: $($service.Status))."
Start-Service -Name$serviceName -ErrorAction Stop
$service.WaitForStatus('Running', (New-TimeSpan -Seconds120))
Write-RemediationLog 'INFO''IME service started.'$changed = $true$restarted = $true
}
else {
Write-RemediationLog 'INFO''IME service already running.'
}
# ---- One controlled restart when the running service is crash-looping ----if (-not $restarted) {
$since = (Get-Date).AddHours(-1 * $LookbackHours)
$crashCount = Get-ScmCrashCount -Since$sinceif ($crashCount -ge$CrashLoopThreshold) {
$agentProcesses = @(Get-Process -Name'AgentExecutor' -ErrorAction SilentlyContinue)
if ($agentProcesses.Count -gt0) {
Write-RemediationLog 'WARN'"AgentExecutor.exe is active ($($agentProcesses.Count) process(es)) - restart skipped so an in-flight install is not interrupted. Re-evaluate on the next run."
}
else {
Write-RemediationLog 'INFO'"Service is running but recorded $crashCount unexpected termination(s) in $LookbackHours hour(s) - performing one controlled restart."
Stop-Service -Name$serviceName -Force -ErrorAction Stop
Start-Service -Name$serviceName -ErrorAction Stop
$service.WaitForStatus('Running', (New-TimeSpan -Seconds120))
Write-RemediationLog 'INFO''Controlled restart completed.'$changed = $true
}
}
else {
Write-RemediationLog 'INFO'"Service running with fewer than $CrashLoopThreshold unexpected termination(s) in the lookback window - no restart needed."
}
}
if ($changed) { Write-RemediationLog 'INFO''IME service remediation applied.' }
else { Write-RemediationLog 'INFO''Device already compliant - no changes made.' }
exit 0
}
catch {
Write-RemediationLog 'ERROR'"Remediation failed: $($_.Exception.Message)"
exit 3
}
finally {
Write-RemediationLog 'INFO''IME service failure remediation run ended.'
}
The gate matters more than the restart. Scripts that blindly bounce a service to "fix" it are the reason users lose installs; this one checks for active install processes first and defers to the next scheduled run instead.
Deploying Through Intune
Deploy both scripts as one remediation package:
Sign in to the Microsoft Intune admin center.
Go to Devices → Scripts and remediations, then select + Add on the Windows 10/11 platform tab.
On the Basics tab, name the package something like Remediate - IME service crash loop, and describe the blast radius ("enables and starts the IME service; one restart at most, skipped when an install is active").
On the Detection script tab, upload detect.ps1. Set Run this script using signed-on credentials: No so it runs as SYSTEM, and Run script in 64-bit PowerShell: Yes.
On the Remediation script tab, upload remediate.ps1 with the same context settings. Leave Enforce script signature check: No unless your organization signs internal scripts and distributes the signing certificates to devices.
On the Schedule tab, choose Daily while a fleet problem is suspected, then relax to Weekly. Crash loops develop over hours, so daily detection catches them quickly without hammering the event log.
On Assignments, target a pilot device group first - ideally a ring that receives Win32 app deployments regularly, since those devices exercise the IME hardest. Exclude kiosks or special-purpose devices where the IME is intentionally absent.
Review and create.
Post-specific notes:
The crash threshold (CrashLoopThreshold) and lookback window (LookbackHours) are script parameters. The defaults - two crashes in 24 hours - are deliberately forgiving; tighten them only after a week of baseline data.
Devices reporting exit code 2 are not installed with the IME at all. Route them to your missing-IME process instead of leaving them in the crash-loop report.
If you prefer to measure first, publish the package with the detection script only for the first week and review the device status view before adding remediation.
Visual Walkthrough
The Management Extension log narrates every app from job to verdict.
TimelineIME Log Forensics — Read It Like a Timeline5/5
T+0 · job
1
Job received
IntuneManagementExtension.log: app + policy arrives with install intent.
download
2
Content download
Win32AppMgr fetches content; watch byte counts and DO involvement.
execute
3
Command execution
AgentExecutor runs install command; exit code recorded verbatim.
detect
4
Detection pass
Detection rule evaluated; mismatch means "reinstall next cycle".
report
5
State reported
Final app state posts to Intune; correlate in the portal report.
IME Log Forensics — Read It Like a Timeline. 1. Job received: IntuneManagementExtension.log: app + policy arrives with install intent. — 2. Content download: Win32AppMgr fetches content; watch byte counts and DO involvement. — 3. Command execution: AgentExecutor runs install command; exit code recorded verbatim. — 4. Detection pass: Detection rule evaluated; mismatch means "reinstall next cycle". — 5. State reported: Final app state posts to Intune; correlate in the portal report.
Exit Codes
Intune runs the detection script and treats any non-zero result as "remediation needed", which triggers the remediation script per your schedule. The codes used here:
Code
Meaning
0
Service present, enabled, running, and no crash-loop pattern - or a single recovered crash (logged as WARN)
1
Service disabled, not running, or two or more unexpected terminations within the lookback window
2
IME not installed - fix by assignment, not by this package
3
Unexpected script error - check the log
On the remediation side, exit 0 means the service was repaired or already compliant. A remediation that reports 3 deserves a look at the local log before you reassign anything.
Logging
Both scripts append to the same structured location:
Each line is a UTC ISO-8601 timestamp, a level (INFO, WARN, ERROR), and a message that names the check and the measured value - crash counts, lookback window, and log scan results included. The directory is created on first run. A few lines per run means retention is rarely a concern, but rotate monthly if your tooling expects bounded files. When the log scan reports elevated error counts, cross-reference the agent's native log at C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.log for the full context.
Troubleshooting the Script
Crash count is always zero but you know devices crash. The query filters on the service display name and short name. If a localized Windows build renders SCM messages differently, widen the filter or drop it temporarily to see the raw events.
Everything reports exit 2. The devices have no IME service - they are either not targeted with any IME-triggering assignment or not enrolled. That is a different problem; split them into their own group.
Remediation keeps logging "restart skipped".AgentExecutor.exe is running whenever the script fires. Your app installs are genuinely busy; lengthen the schedule or accept that the restart happens on a quieter run.
No log file appears. The script never ran. Check the assignment, confirm the device last checked in, and verify nothing blocked script execution - review the IntuneManagementExtension log for script download failures.
Event query throws in a manual console run. You are probably in a 32-bit PowerShell session or a non-elevated one. Both detection and remediation require an elevated 64-bit Windows PowerShell session, exactly like the Intune runtime provides.
How to Validate the Fix
On a lab device, stop the IME service (Stop-Service IntuneManagementExtension) and run detection manually in an elevated 64-bit console. Expect exit code 1 and an ERROR line naming the stopped service.
Run remediation manually. Expect exit code 0, with log lines showing the start action and the wait for the running state.
Re-run detection. It must now return 0 and log the service status and crash count.
To exercise the crash-loop path, induce two service terminations (or temporarily lower CrashLoopThreshold to 1 in a test copy), confirm detection exits 1, then confirm remediation performs exactly one restart and skips further restarts while AgentExecutor.exe is active.
In the admin center, open the package's Device status view. The test device should appear as "Remediated" after its next sync.
Production Considerations
Execution context. Both scripts run as SYSTEM in 64-bit Windows PowerShell. They read only machine-scoped state: the service control database, the System event log, and the agent log under ProgramData.
Idempotency. Detection never changes the device. Remediation performs each action only when its precondition holds, and the restart happens at most once per run, so repeated scheduling cannot create restart storms.
Side effects and reboots. Enabling and starting a service needs no reboot. The single gated restart interrupts nothing that is installing, because AgentExecutor.exe activity is checked first; worst case, the restart is deferred to the next scheduled run.
Security. No credentials or secrets appear in the scripts, and every action uses built-in cmdlets. Have your PowerShell automation SME and security team review the scripts and prove them in a test ring - including the restart gate - before assigning the package broadly in production.
Scope control. Assign through a group you can empty quickly if the restart behavior surprises you; removing the assignment halts new runs everywhere without touching any device.
Why doesn't a single crash trigger remediation?
One unexpected termination followed by stable operation is normal after agent upgrades and transient resource pressure. Restarting a service that is currently healthy buys nothing and adds churn. The CrashLoopThreshold parameter lets you change this once you know your fleet's baseline.
Can the restart interrupt an application install?
Not by design. Before restarting, the remediation checks for active AgentExecutor.exe processes - the child process that runs Win32 installs - and skips the restart entirely if any are running, logging the decision instead. The next scheduled run gets a fresh chance.
Should I also alert on the raw event log?
Yes, if you have a monitoring pipeline. Event IDs 7031 and 7034 from Service Control Manager naming the IME service are the same raw signal this script uses, so a dashboard on those events complements the device-level detection nicely.
Comments
0No comments yet — be the first to share your thoughts.