Detect Intune IME Log Errors with PowerShell Analysis · CloudEngineerHub
Detection & Remediation10 min read4 views
Detecting Intune IME Log Errors with PowerShell Log Analysis
A detection-only PowerShell scan of the Intune Management Extension log: shared-access reading, CMTrace severity parsing, and the top five recurring error patterns with counts.
C
CloudEngineerHub Team
Published: September 10, 2026· Last Updated: September 28, 2026·10 min read
When a Win32 app fails or a script misbehaves on one device out of a thousand, the answer is almost always sitting in IntuneManagementExtension.log. The problem is that nobody has time to read a multi-megabyte log per device, and the admin center gives you exit codes, not narrative. What you need is a way to ask each device a simple question: how unhappy has your agent been lately, and about what? A structured scan of the IME log answers that with numbers instead of anecdotes.
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 article provides a detection-only script that reads the IME log, counts ERROR and warning entries inside a configurable time window, and reports the most frequent error patterns with occurrence counts. It parses the CMTrace format the agent actually writes, handles timestamps defensively, and opens the file with shared access so the running agent is never disturbed. Because it is detection-only, you can assign it broadly and safely: the worst thing it does is write its own log file.
The output is deliberately boring: a count, a window, and the top five recurring error shapes per device. Boring output is what makes it usable as a fleet-wide report and as a triage pointer that tells you which devices deserve a human reading the full log.
Symptoms
Log analysis becomes necessary when the portal stops explaining the problem:
A Win32 app fails on specific devices with an exit code that does not map to anything documented, and the IME log is the only place the real error text exists.
Remediation packages report errors on a scattered subset of devices with no obvious common factor.
Users report apps "stuck installing" and the portal status never changes.
After an agent upgrade or a network change, you want to know whether error rates rose before users notice.
You inherit devices with months of IME history and no idea which failures are chronic versus incidental.
Possible Causes
Recurring IME log errors trace back to a handful of families:
Download and connectivity failures
The agent fails to reach content or service endpoints: proxy changes, TLS inspection, DNS problems, or transient network drops. These produce clusters of errors around specific times, which the time window makes visible.
Installer execution failures
The app's own setup returns a failure. The IME logs the execution attempt, the return code, and the failure, faithfully and repeatedly when retries run. The pattern here names the app or installer, which is exactly what grouping surfaces.
State and cache corruption
When the agent's local cache or state files are damaged, errors repeat in a stable pattern across app operations. These patterns persist across days, unlike one-off installer failures.
Agent upgrade issues
The IME upgrades itself, and upgrade hiccups produce error bursts around upgrade timestamps. Recognizing this pattern prevents misattributing agent problems to app assignments.
Environmental noise
Antivirus interference, permission problems on folders the agent writes, and disk-full conditions each leave characteristic error sequences. None of them are Intune's fault, and all of them are easier to see in counts than in raw text.
Detection Script
The script below is read-only and typically completes in seconds; very large or busy logs can push it toward a minute. It runs in 64-bit SYSTEM context, requires no modules, and opens the log with FileShare.ReadWrite so it works while the agent is actively writing.
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#Requires -RunAsAdministrator
[CmdletBinding()]
param(
[ValidateRange(1, 720)]
[int] $LookbackHours = 24,
[ValidateRange(1, 20)]
[int] $TopPatterns = 5,
[ValidateRange(1, 10000)]
[int] $ErrorThreshold = 1
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
<#
.SYNOPSIS
Detection script: scans the Intune Management Extension log for ERROR and
WARN entries inside a time window and reports the most frequent patterns.
.DESCRIPTION
The IME writes its log in CMTrace format:
<![LOG[message]LOG]!><time="..." date="..." component="..." type="N" ...>
where the type attribute is the severity (3 = error, 2 = warning). This
script:
- Reads the log with shared access so the running agent is never
disturbed.
- Parses the time/date attributes defensively; lines whose timestamps
cannot be parsed are counted and reported, never silently dropped
into a severity bucket.
- Falls back to literal [ERROR]/[WARN] tokens for lines that lack a
CMTrace structure.
- Groups error messages into patterns (component plus message with
GUIDs and long numbers normalized away) and reports the top ones.
This script NEVER changes the system. Exit 0 = fewer errors than the
threshold in the window, 1 = error count at or above the threshold,
2 = IME log not present (agent likely not installed), 3 = unexpected error.
#>$logDir = 'C:\ProgramData\Company\Logs'$logFile = Join-Path $logDir'ImeLogErrorDetection.log'$imeLogPath = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.log'$regexMessage = [regex]'<!\[LOG\[(?<message>.*?)\]LOG\]!'$regexType = [regex]'type="(?<type>\d+)"'$regexTime = [regex]'time="(?<time>[^"]+)"\s+date="(?<date>[^"]+)"'$regexComp = [regex]'component="(?<component>[^"]+)"'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-LogTimestamp {
param([Parameter(Mandatory)][string] $Line)
$timeMatch = $regexTime.Match($Line)
if (-not $timeMatch.Success) { return$null }
try {
$datePart = [datetime]::ParseExact($timeMatch.Groups['date'].Value, 'M-d-yyyy', [System.Globalization.CultureInfo]::InvariantCulture)
$timePart = [timespan]::Parse($timeMatch.Groups['time'].Value, [System.Globalization.CultureInfo]::InvariantCulture)
return$datePart.Add($timePart)
}
catch {
return$null
}
}
function Get-ErrorSignature {
param([Parameter(Mandatory)][string] $Component, [Parameter(Mandatory)][string] $Message)
$normalized = $Message -replace'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', '{guid}'$normalized = $normalized -replace'\d{4,}', '{n}'if ($normalized.Length -gt120) { $normalized = $normalized.Substring(0, 120) }
return"${Component} :: ${normalized}"
}
try {
Write-DetectionLog 'INFO'"IME log error detection started. LookbackHours=$LookbackHours."if (-not (Test-Path -LiteralPath$imeLogPath)) {
Write-DetectionLog 'ERROR'"IME log not found at $imeLogPath. The agent is likely not installed; IME installs when the device is first targeted with a Win32 app or required system script."
exit 2
}
$cutoff = (Get-Date).AddHours(-$LookbackHours)
$errorCount = 0$warnCount = 0$unparsable = 0$linesScanned = 0$patterns = @{}
$samples = @{}
# Shared read access: the IME keeps this file open for writing.$stream = [System.IO.File]::Open($imeLogPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$reader = New-Object System.IO.StreamReader($stream)
try {
while ($null -ne ($line = $reader.ReadLine())) {
$linesScanned++
$msgMatch = $regexMessage.Match($line)
if (-not $msgMatch.Success) { continue }
$timestamp = Get-LogTimestamp -Line$lineif ($null -eq$timestamp) {
$unparsable++
continue
}
if ($timestamp -lt$cutoff) { continue }
$severity = $null$typeMatch = $regexType.Match($line)
if ($typeMatch.Success) {
if ($typeMatch.Groups['type'].Value -eq'3') { $severity = 'ERROR' }
elseif ($typeMatch.Groups['type'].Value -eq'2') { $severity = 'WARN' }
}
if ($null -eq$severity) {
$messageText = $msgMatch.Groups['message'].Value
if ($messageText.Contains('[ERROR]')) { $severity = 'ERROR' }
elseif ($messageText.Contains('[WARN]')) { $severity = 'WARN' }
}
if ($null -eq$severity) { continue }
if ($severity -eq'ERROR') { $errorCount++ }
else { $warnCount++ }
$component = 'unknown'$compMatch = $regexComp.Match($line)
if ($compMatch.Success) { $component = $compMatch.Groups['component'].Value }
$signature = Get-ErrorSignature -Component$component -Message$msgMatch.Groups['message'].Value
if (-not $patterns.ContainsKey($signature)) {
$patterns[$signature] = 0$samples[$signature] = $msgMatch.Groups['message'].Value.Substring(0, [math]::Min(200, $msgMatch.Groups['message'].Value.Length))
}
$patterns[$signature] = $patterns[$signature] + 1
}
}
finally {
$reader.Close()
$stream.Close()
}
Write-DetectionLog 'INFO'"Scanned $linesScanned log lines. Window: last $LookbackHours hour(s). Errors=$errorCount Warnings=$warnCount UnparsableTimestamps=$unparsable."$top = $patterns.GetEnumerator() | Sort-Object -Property Value -Descending | Select-Object -First$TopPatternsif (@($top).Count -gt0) {
foreach ($entryin @($top)) {
Write-DetectionLog 'WARN' ("Pattern ({0} occurrence(s)): {1}" -f$entry.Value, $entry.Key)
}
}
else {
Write-DetectionLog 'INFO''No error or warning entries found in the lookback window.'
}
if ($errorCount -ge$ErrorThreshold) {
Write-DetectionLog 'ERROR'"IME log contains $errorCount error entr(ies) in the last $LookbackHours hour(s), at or above the threshold of $ErrorThreshold."
exit 1
}
Write-DetectionLog 'INFO'"Error count below threshold. Device log looks healthy for the window."
exit 0
}
catch {
Write-DetectionLog 'ERROR'"Unexpected failure: $($_.Exception.Message)"
exit 3
}
finally {
Write-DetectionLog 'INFO''IME log error detection finished.'
}
Detection Logic
The scan works the way you would read the log by hand, just faster and without fatigue:
Shared-access read. The log is opened with a FileStream that requests read access while permitting the agent's write share. This is the difference between a script that works on live devices and one that fails with file-in-use errors.
CMTrace parsing. Each line is matched against the <![LOG[... ]LOG]!> envelope. Lines outside that structure (some agent tooling writes plain text) are skipped for severity purposes. The type attribute carries the severity: 3 means error, 2 means warning. This is the documented CMTrace convention, and the IME follows it.
Defensive timestamps. The time and date attributes are parsed into a real DateTime (date format M-d-yyyy, time parsed as a TimeSpan to tolerate fractional seconds). Lines whose timestamps cannot be parsed are counted and reported as UnparsableTimestamps instead of being guessed into the window.
Fallback tokens. A line with no usable type attribute but a literal [ERROR] or [WARN] token in the message is still classified, so real signals survive format drift.
Window filtering. Only entries newer than $LookbackHours (default 24) are counted. Old history stays out of today's verdict.
Pattern grouping. Every error and warning is reduced to a signature: the component attribute plus the message with GUIDs and long digit runs normalized to placeholders, truncated to 120 characters. Signatures are counted in a hashtable; the top $TopPatterns (default 5) are written to the log with occurrence counts and one 200-character sample each.
The exit decision uses only the ERROR count: at or above $ErrorThreshold (default 1) is exit code 1; below it is exit code 0. Warnings are reported but do not fail the device, because IME logs routinely contain benign warnings that would make a warning-sensitive threshold useless.
Deploying Through Intune
This is a detection-only package; choose No remediation script.
In the Microsoft Intune admin center, go to Devices → Scripts and remediations and select + Add on the Windows 10/11 tab.
On Basics, name it Audit - IME log error scan, with a description stating it only reads the agent log.
On Detection script, upload detect.ps1. Set Run script in 64-bit PowerShell: Yes and Run this script using signed-on credentials: No; the log is machine-scoped under C:\ProgramData.
On the Remediation script step, choose No remediation script. Log analysis does not repair anything; it points you at what needs repair.
Leave Enforce script signature check: No unless you sign internal scripts.
On Schedule, Daily gives you a rolling error rate per device. During a troubleshooting sprint on a specific app, Weekly on the affected cohort reduces noise.
On Assignments, start with the devices experiencing the problem, then widen to a representative sample of healthy devices so you have a baseline to compare error patterns against.
Review and create.
Post-specific notes:
Tune $LookbackHours to the question: 24 for daily hygiene, 168 for "what changed this week".
$ErrorThreshold default 1 flags any error at all; on messy fleets, start higher (for example 5) and tighten once the chronic noise is understood.
The top-pattern lines are the deliverable; wire them into your reporting before assigning broadly.
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 evaluates the detection script; any non-zero marks the device as an issue in the package's device status view.
Code
Meaning
0
Error count in the window is below the threshold
1
Error count is at or above the threshold; top patterns are in the log
2
IME log not present; the agent is likely not installed
3
Unexpected script error; inspect the log
Logging
The script writes to C:\ProgramData\Company\Logs\ImeLogErrorDetection.log. Each line carries a UTC timestamp, a level (INFO, WARN, ERROR), and a message. The run summary line records lines scanned, errors, warnings, and unparsable timestamps; each top pattern logs its occurrence count and normalized signature. The script's own log grows slowly, but note that the IME log it reads has its own size behavior; the agent manages that file's rotation, and this script never deletes or truncates it. For deeper analysis, the same folder holds sibling logs such as AgentExecutor.log for script execution detail, which you can inspect manually once this scan tells you which devices and time windows matter.
Troubleshooting the Script
Exit code 3 with a file access error. Something is holding the log with an exclusive share. Security tooling that mirrors files can cause this; identify the locker rather than copying the file with forced handles.
Everything reports "IME log not found". Either the devices genuinely lack the agent (exit 2 is correct) or the platform check failed; remember the IME only installs after a Win32 app or required script targets the device.
UnparsableTimestamps is high. Usually means an agent version wrote a format variant. The script stays honest and reports them; sample a few lines manually and, if needed, extend the parse formats rather than assuming those lines are clean.
One giant pattern dominates. A chatty repeated error (for example, a retry loop) produces one signature with hundreds of counts. That is useful information: read the sample text, then look at timestamps around it in the raw log.
Results differ between two runs minutes apart. The agent is actively writing; the window moves with wall-clock time. For stable comparisons, compare devices against each other rather than a device against itself across hours.
How to Validate the Fix
Validation here means proving the scan reads the log the way you would:
On a test device, run the script manually in an elevated 64-bit PowerShell console on a healthy day. Expect exit code 0 and a summary line with low or zero errors.
Trigger a known failure, for example assign a Win32 app that deliberately fails, then re-run with a short lookback. Expect exit code 1 and a top pattern whose text names the failure.
Confirm the summary counts by spot-checking the raw log for type="3" occurrences inside the window on one device.
Create a log line with an unparseable timestamp in a copy of the log, point a test run at it by temporarily adjusting the path in a lab copy, and confirm it lands in UnparsableTimestamps rather than in a severity bucket.
In the admin center, confirm device status for the package matches the manual runs, then use the top-pattern report in your troubleshooting workflow.
Production Considerations
Execution context. The script runs as SYSTEM in 64-bit Windows PowerShell. Reading C:\ProgramData requires no user token, and no user data is touched.
Idempotency. Detection-only: it opens the log for shared reading and writes only its own log file. The IME log is never modified, rotated, or deleted by this script.
Side effects. None beyond the read I/O. On devices with enormous logs the scan is CPU- and disk-bound for its duration; schedule it outside peak hours if that matters on constrained hardware.
Security. No credentials appear in the script. The log may contain user names or device names in error text; treat the script's own log with the same sensitivity as the source log when exporting it. Have your PowerShell automation SME and security team review the scripts and validate them in a test ring before broad production rollout.
False-positive budget. Any error-count threshold produces noise on real fleets. Calibrate against a baseline week rather than shipping the defaults everywhere.
Why parse the CMTrace type attribute instead of searching for the word "error"?
Because error text appears in messages that are not errors, and severity words appear in different casing or context. The type attribute is the structured severity the CMTrace format was designed to carry, with 3 meaning error and 2 meaning warning, so it is the only signal that does not lie. The literal [ERROR]/[WARN] token check exists only as a fallback for lines that lack the structured envelope.
Will the script interfere with the running IME agent?
No. It opens the log with a shared read that explicitly permits the agent's write access, reads to the end, and closes. The agent keeps writing throughout, and the script never requests exclusive access or attempts any modification of the file.
The script found the top error patterns. What do I do with them?
Treat each pattern as a lead, not a verdict. Take the normalized signature, find matching lines in the raw log on one device, read the surrounding context (what the agent attempted just before), and check whether the pattern correlates with a specific app, time window, or network location. That is usually enough to route the problem to the right owner: content, connectivity, packaging, or the agent itself.
Comments
0No comments yet — be the first to share your thoughts.