diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fba99c..80444bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,16 @@ release notes. ## [Unreleased] -Nothing yet. +### Fixed + +- `Get-IntuneAgentTimeline` reported `Kind` as `Unknown` for a policy or app whose lines all sat in + a rolled log file: the rolled name (`HealthScripts-20260925-101500`) lost only its time part, so it + never matched the log table. Both parts come off now, and such a timeline reads as Remediation or + Win32App like one from the current file. +- The README's Enrollment Status Page block showed the `Log` column before it abbreviated + `IntuneManagementExtension` to `Agent`, and its diagnostic block showed the result as a table + where it has printed as a list with the size in MB since 0.28.0. Both now show what the commands + print. ## [0.31.0] - 2026-10-09 diff --git a/Private/ConvertFrom-IslCmTraceLog.ps1 b/Private/ConvertFrom-IslCmTraceLog.ps1 index 51ec34a..87db2aa 100644 --- a/Private/ConvertFrom-IslCmTraceLog.ps1 +++ b/Private/ConvertFrom-IslCmTraceLog.ps1 @@ -16,8 +16,8 @@ function ConvertFrom-IslCmTraceLog { and Id are left empty for Get-IntuneAgentLog to fill. The filters are the ones Get-IntuneAgentLog offers, applied to the raw record before an - object is built for it. Building the object is most of what an entry costs, so a filtered - read of a 22 MB log takes seconds where building every entry takes a minute. + object is built for it. Building the object is most of what an entry costs: on a 15 MB log + of 80,000 entries, one policy by -Id reads in 5 seconds where every entry takes 30. .PARAMETER Path The log file to parse. @@ -91,7 +91,7 @@ function ConvertFrom-IslCmTraceLog { $ordinalIgnoreCase = [System.StringComparison]::OrdinalIgnoreCase $ordinal = [System.StringComparison]::Ordinal - # An agent log of 22 MB is 80,000 entries, and every statement here runs once per entry. The + # An agent log of 15 MB is 80,000 entries, and every statement here runs once per entry. The # attributes come out of one compiled regex in the order the agent writes them, the timestamp # is read the way ConvertTo-IslCmTraceTime reads it without the call, and the filters run on # the raw strings before anything is built. Lines are counted only up to an entry that is kept diff --git a/Public/Get-IntuneAgentTimeline.ps1 b/Public/Get-IntuneAgentTimeline.ps1 index 046a906..60fe771 100644 --- a/Public/Get-IntuneAgentTimeline.ps1 +++ b/Public/Get-IntuneAgentTimeline.ps1 @@ -56,7 +56,9 @@ function Get-IntuneAgentTimeline { Message = $_.Message } }) - $logsSeen = @($steps | ForEach-Object { $_.Log -replace '-\d+$', '' } | Sort-Object -Unique) + # A rolled file is HealthScripts-20260925-101500: both date and time come off, or the name + # never matches the table and a policy whose lines all sit in a rolled file reads as Unknown + $logsSeen = @($steps | ForEach-Object { $_.Log -replace '-\d{8}-\d{6}$', '' } | Sort-Object -Unique) $kind = 'Unknown' foreach ($seen in $logsSeen) { if ($kindByLog.ContainsKey($seen)) { $kind = $kindByLog[$seen]; break } diff --git a/README.md b/README.md index 75924fb..ea94742 100644 --- a/README.md +++ b/README.md @@ -438,19 +438,20 @@ shared access, so the live agent is no obstacle, and a copied log folder works w ```powershell Get-IntuneAgentLog -EventName ScriptEspPhase, EspPhase, EspAppsSelected, EspAppRegistered, - EspAppState, EspPhaseComplete, EspComplete, EspNontrackedCheckin - -Time Log Event Detail ----- --- ----- ------ -09-28 07:06:00.847 IntuneManagementExtension ScriptEspPhase DeviceSetup -09-28 07:06:12.299 AppWorkload EspPhase DeviceSetup -09-28 07:06:25.611 AppWorkload EspAppsSelected 2 -09-28 07:06:31.011 AppWorkload EspAppRegistered DeviceSetup ISL-ESP-DEV-W32-BLOCK1 -09-28 07:07:31.199 AppWorkload EspAppState InProgress Completed -09-28 07:08:20.385 AppWorkload EspPhaseComplete device -09-28 07:08:37.882 AppWorkload EspPhase AccountSetup -09-28 07:11:22.504 AppWorkload EspComplete -09-28 07:12:22.658 IntuneManagementExtension EspNontrackedCheckin True + EspAppState, EspPhaseComplete, EspComplete, EspNontrackedCheckin | + Format-Table Time, Log, Event, Detail + +Time Log Event Detail +---- --- ----- ------ +09-28 07:06:00.847 Agent ScriptEspPhase DeviceSetup +09-28 07:06:12.299 AppWorkload EspPhase DeviceSetup +09-28 07:06:25.611 AppWorkload EspAppsSelected 2 +09-28 07:06:31.011 AppWorkload EspAppRegistered DeviceSetup ISL-ESP-DEV-W32-BLOCK1 +09-28 07:07:31.199 AppWorkload EspAppState InProgress Completed +09-28 07:08:20.385 AppWorkload EspPhaseComplete device +09-28 07:08:37.882 AppWorkload EspPhase AccountSetup +09-28 07:11:22.504 AppWorkload EspComplete +09-28 07:12:22.658 Agent EspNontrackedCheckin True ``` One Autopilot run (Validation\Findings.md, "The Enrollment Status Page") fixed where scripts sit @@ -474,9 +475,12 @@ Started Kind Name Duration Runs Outcome Export-IntuneAgentDiagnostic -Path C:\Temp\intune-diag.zip -Path Files Logs Registry Timeline SizeBytes ----- ----- ---- -------- -------- --------- -C:\Temp\intune-diag.zip 14 6 True True 2318402 +Path : C:\Temp\intune-diag.zip +Size : 2.9 MB +Files : 29 +Logs : 20 +Registry : True +Timeline : True ``` `Get-IntuneAgentTimeline` groups the named log lines by the policy or app they belong to, so one diff --git a/Tests/Unit/Public/Get-IntuneAgentTimeline.Tests.ps1 b/Tests/Unit/Public/Get-IntuneAgentTimeline.Tests.ps1 index 460ba84..e429444 100644 --- a/Tests/Unit/Public/Get-IntuneAgentTimeline.Tests.ps1 +++ b/Tests/Unit/Public/Get-IntuneAgentTimeline.Tests.ps1 @@ -116,6 +116,24 @@ Describe 'Get-IntuneAgentTimeline' -Tag 'Unit', 'Public' { $platform.Outcome | Should-Be 'ScriptPolicyResult Failed' $platform.Duration.TotalSeconds | Should-Be 20 } + + It 'reads the kind from a rolled log file as it does from the current one' { + # The agent rolls HealthScripts.log over to HealthScripts--