From 4a3a3f1df5aab7513a245818bcd83842225b9f18 Mon Sep 17 00:00:00 2001 From: YeehomZhu Date: Fri, 24 Apr 2026 13:48:56 +1000 Subject: [PATCH] Add run summary _SUMMARY.txt, Delivery Optimization diagnostics, and Settings Catalog policy state Intune.xml: - Add Delivery Optimization commands (Get-DeliveryOptimizationStatus, PerfSnap, DOConfig, bandwidth caps) - Add Microsoft-Windows-DeliveryOptimization event log capture - Add PolicyManager registry exports: current, providers, AdmxInstalled, AdmxDefault (Settings Catalog state) IntuneODCStandAlone.ps1: - Add Write-RunSummary function generating _SUMMARY.txt at root of collected data - Captures ODC version, run duration, OS, file count, total size - Surfaces key health indicators (AAD/Domain/Workplace join, IME service, MDM cert expiry, free disk space, ODC log errors) - Items flagged with [!] for quick triage --- Intune.xml | 13 ++++- IntuneODCStandAlone.ps1 | 110 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/Intune.xml b/Intune.xml index 91df472..f5e5a44 100644 --- a/Intune.xml +++ b/Intune.xml @@ -3987,6 +3987,12 @@ del .\*DiagnosticLogCSP_Collector*.etl reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Appraiser\GWX" Get-DeliveryOptimizationLog + RunCommand "Get-DeliveryOptimizationStatus" +RunCommand "Get-DeliveryOptimizationPerfSnap" +RunCommand "Get-DeliveryOptimizationPerfSnapThisMonth" +RunCommand "Get-DOConfig -Verbose" +RunCommand "Get-DOPercentageMaxBackgroundBandwidth" +RunCommand "Get-DOPercentageMaxForegroundBandwidth" $ServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager" echo "`$ServiceManager = New-Object -ComObject Microsoft.Update.ServiceManager;`$ServiceManager.services| fl *" echo $("*" * 60) @@ -5253,6 +5259,7 @@ $resultBlob | Format-List %SystemRoot%\system32\winevt\logs\*appx* %SystemRoot%\system32\winevt\logs\*bitlocker* %SystemRoot%\system32\winevt\logs\*defender* + %SystemRoot%\system32\winevt\logs\*DeliveryOptimization* %SystemRoot%\system32\winevt\logs\*devicemanagement* %SystemRoot%\system32\winevt\logs\*firewall* %SystemRoot%\system32\winevt\logs\*intune* @@ -5365,7 +5372,11 @@ $resultBlob | Format-List HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CloudManagedUpdate - HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\current\device\Update + HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\current\device\Update + HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\current + HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\providers + HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\AdmxInstalled + HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\AdmxDefault HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WufbDS diff --git a/IntuneODCStandAlone.ps1 b/IntuneODCStandAlone.ps1 index 5d6bbea..05bebbf 100644 --- a/IntuneODCStandAlone.ps1 +++ b/IntuneODCStandAlone.ps1 @@ -1,4 +1,4 @@ -<# +<# Stand-alone implementation of One Data Collector #> @@ -40,7 +40,8 @@ $CompressedResultFileName = "$($env:COMPUTERNAME)_CollectedData_$fileTime.ZIP" [System.Nullable[bool]] $newZipperAvailable = $null # Stores flag whether [System.IO.Compression.ZipFile] can be used. $global:LogName = "$env:systemroot\temp\stdout.log" -$ODCversion = "2026.3.23" +$ODCversion = "2026.4.24" +$Global:ScriptStartTime = Get-Date #endregion @@ -1702,10 +1703,115 @@ function Process-Package } } +function Write-RunSummary { + <# + .SYNOPSIS + Generates a _SUMMARY.txt at the root of the collected data folder so engineers + triaging the ZIP can immediately see run metadata and key health indicators. + #> + if (-not (Test-Path $ResultRootDirectory)) { return } + + $summaryPath = Join-Path $ResultRootDirectory '_SUMMARY.txt' + $endTime = Get-Date + $duration = $endTime - $Global:ScriptStartTime + + $sb = New-Object System.Text.StringBuilder + [void]$sb.AppendLine(('=' * 80)) + [void]$sb.AppendLine(" Intune One Data Collector (ODC) - Run Summary") + [void]$sb.AppendLine(('=' * 80)) + [void]$sb.AppendLine("ODC Version : $ODCversion") + [void]$sb.AppendLine("Computer Name : $env:COMPUTERNAME") + [void]$sb.AppendLine("User : $env:USERDOMAIN\$env:USERNAME") + [void]$sb.AppendLine("Run Start (Local) : $($Global:ScriptStartTime.ToString('yyyy-MM-dd HH:mm:ss zzz'))") + [void]$sb.AppendLine("Run End (Local) : $($endTime.ToString('yyyy-MM-dd HH:mm:ss zzz'))") + [void]$sb.AppendLine("Duration : {0:c}" -f $duration) + + try { + $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop + [void]$sb.AppendLine("OS : $($os.Caption) (Build $($os.BuildNumber))") + } catch { [void]$sb.AppendLine("OS : (unable to query)") } + + # Folder size + file count + try { + $items = Get-ChildItem -Path $ResultRootDirectory -Recurse -File -ErrorAction SilentlyContinue + $totalBytes = ($items | Measure-Object -Property Length -Sum).Sum + [void]$sb.AppendLine("Files Collected : $($items.Count)") + [void]$sb.AppendLine("Total Size : {0:N2} MB" -f ($totalBytes / 1MB)) + } catch {} + + [void]$sb.AppendLine('') + [void]$sb.AppendLine(('-' * 80)) + [void]$sb.AppendLine(" Key Health Indicators") + [void]$sb.AppendLine(('-' * 80)) + + # Azure AD / MDM enrollment state + try { + $ds = dsregcmd /status 2>$null + $aadJoined = if ($ds -match 'AzureAdJoined\s*:\s*YES') { 'YES' } else { 'NO' } + $domJoined = if ($ds -match 'DomainJoined\s*:\s*YES') { 'YES' } else { 'NO' } + $workplace = if ($ds -match 'WorkplaceJoined\s*:\s*YES') { 'YES' } else { 'NO' } + [void]$sb.AppendLine("AzureAdJoined : $aadJoined") + [void]$sb.AppendLine("DomainJoined : $domJoined") + [void]$sb.AppendLine("WorkplaceJoined : $workplace") + } catch { [void]$sb.AppendLine("dsregcmd : (failed to run)") } + + # IME service state + try { + $ime = Get-Service -Name IntuneManagementExtension -ErrorAction Stop + $marker = if ($ime.Status -ne 'Running') { ' [!]' } else { '' } + [void]$sb.AppendLine("IME Service : $($ime.Status) (StartType: $($ime.StartType))$marker") + } catch { [void]$sb.AppendLine("IME Service : NOT INSTALLED [!]") } + + # MDM enrollment cert + try { + $cert = Get-ChildItem Cert:\LocalMachine\My -ErrorAction SilentlyContinue | + Where-Object { $_.Issuer -match 'CN=Microsoft Intune MDM Device CA' } | + Sort-Object NotAfter -Descending | Select-Object -First 1 + if ($cert) { + $daysLeft = ($cert.NotAfter - (Get-Date)).Days + $marker = if ($daysLeft -lt 30) { ' [!]' } else { '' } + [void]$sb.AppendLine("MDM Cert Expires : $($cert.NotAfter.ToString('yyyy-MM-dd')) ($daysLeft days)$marker") + } else { + [void]$sb.AppendLine("MDM Cert : NOT FOUND") + } + } catch {} + + # Disk space on system drive + try { + $drive = Get-PSDrive -Name ($env:SystemDrive.TrimEnd(':')) -ErrorAction Stop + $freeGB = [math]::Round($drive.Free / 1GB, 1) + $marker = if ($freeGB -lt 5) { ' [!]' } else { '' } + [void]$sb.AppendLine("Free Space ($($env:SystemDrive)) : $freeGB GB$marker") + } catch {} + + # Errors observed in the ODC log itself + try { + if (Test-Path $global:LogName) { + $errCount = (Get-Content $global:LogName -ErrorAction SilentlyContinue | + Select-String -Pattern '\bError\b|\bException\b|\bFailed\b' -CaseSensitive:$false | + Where-Object { $_ -notmatch 'SilentlyContinue|ErrorAction|ErrorVariable|ErrorActionPreference|FullyQualifiedErrorId|No errors' }).Count + $marker = if ($errCount -gt 0) { ' [!]' } else { '' } + [void]$sb.AppendLine("ODC Log Errors : $errCount$marker") + } + } catch {} + + [void]$sb.AppendLine('') + [void]$sb.AppendLine('Items flagged with [!] may warrant investigation.') + [void]$sb.AppendLine(('=' * 80)) + + try { + Set-Content -Path $summaryPath -Value $sb.ToString() -Encoding UTF8 -Force + Write-Log -Message "Run summary written to $summaryPath" -Level Information + } catch { + Write-Log -Message "Failed to write run summary: $_" -Level Warning + } +} + function Compress-CollectedDataAndReport { if(Test-Path($ResultRootDirectory)) { + Write-RunSummary Write-DiagProgress -Activity "Compressing zip file" -status $CompressedResultFileName