Public/Get-UpdateFailureReport.ps1

function Get-UpdateFailureReport {
    <#
    .SYNOPSIS
        Provides a concise, user-facing Windows Update servicing failure report.
 
    .DESCRIPTION
        Thin public wrapper around the internal diagnostic analyzer (Get-ServicingDiagnostics).
        Focuses on quickly surfacing categorized servicing issues (DISM/CBS), unrepaired component
        counts, pending reboot indicators, and actionable recommendations – without exposing the
        full underlying parsing complexity by default. Use -Detailed to attach the full raw
        diagnostics object for deeper programmatic analysis.
 
        Defaults to tail sampling (last 800 lines) for speed; specify -Full for complete log scan.
 
    .PARAMETER Tail
        Number of trailing lines from each log (DISM / CBS) to sample (ignored when -Full). Default 800.
 
    .PARAMETER Full
        Parse entire dism.log and CBS.log (may be slower on large systems). Overrides -Tail.
 
    .PARAMETER IncludeSFC
        Include SFC ([SR]) events discovered in CBS.log in the detailed diagnostics object (only visible with -Detailed).
 
    .PARAMETER IncludeRaw
        Include raw matched error lines / CannotRepair samples (only visible with -Detailed or JSON export).
 
    .PARAMETER ExportJsonPath
        Optional path to write the full detailed diagnostics object (JSON). Useful for offline triage.
 
    .PARAMETER LogPath
        Optional module log file path to append the summarized report.
 
    .PARAMETER Detailed
        Attach the complete underlying diagnostics object (as DetailedDiagnostics) to the returned summary.
 
    .EXAMPLE
        Get-UpdateFailureReport
 
        Tail-samples logs and returns a concise summary of servicing issues.
 
    .EXAMPLE
        Get-UpdateFailureReport -Full -Detailed -ExportJsonPath C:\Temp\WU-Diag.json
 
        Performs full log scan, returns summary plus full diagnostics object, and exports JSON.
 
    .OUTPUTS
        PSCustomObject with properties:
          Timestamp
          Success
          Categories
          Codes (Code, Category, Count)
          UnrepairedComponentCount
          PendingReboot
          PendingRebootReasons
          Recommendations
          FullScan (Boolean)
          TailSampleSize (lines used when not Full)
          DetailedDiagnostics (present only with -Detailed)
 
    .NOTES
        Author: CSOLVE
        Wrapper Version: 1.0.0
    #>

    [CmdletBinding()] param(
        [int]$Tail = 800,
        [switch]$Full,
        [switch]$IncludeSFC,
        [switch]$IncludeRaw,
        [string]$ExportJsonPath,
        [string]$LogPath,
        [switch]$Detailed
    )

    if ($Tail -le 0 -and -not $Full) { throw 'Tail must be > 0 unless -Full is specified.' }

    $diagParams = @{}
    if ($Full) { $diagParams.Full = $true } else { $diagParams.Tail = $Tail }
    if ($IncludeSFC) { $diagParams.IncludeSFCEvents = $true }
    if ($IncludeRaw) { $diagParams.IncludeRaw = $true }
    if ($ExportJsonPath) { $diagParams.ExportJsonPath = $ExportJsonPath }
    if ($LogPath) { $diagParams.LogPath = $LogPath }

    $diag = Get-ServicingDiagnostics @diagParams

    $summary = [PSCustomObject]@{
        Timestamp = $diag.Timestamp
        Success = $diag.Success
        Categories = $diag.Categories
        Codes = $diag.Codes | Select-Object Code, Category, Count
        UnrepairedComponentCount = $diag.CbsCannotRepairCount
        PendingReboot = $diag.PendingReboot
        PendingRebootReasons = $diag.PendingRebootReasons
        Recommendations = $diag.Recommendations
        FullScan = [bool]$Full
        TailSampleSize = if ($Full) { $null } else { $Tail }
        DetailedDiagnostics = if ($Detailed) { $diag } else { $null }
    }

    if ($LogPath) {
        try {
            Write-WULog -Message '=== Windows Update Failure Report ===' -LogPath $LogPath
            Write-WULog -Message ("Categories: {0}" -f ([string]::Join(',', $summary.Categories))) -LogPath $LogPath
            Write-WULog -Message ("Codes: {0}" -f ([string]::Join(',', ($summary.Codes | ForEach-Object { $_.Code })))) -LogPath $LogPath
            Write-WULog -Message ("Unrepaired Components: {0}" -f $summary.UnrepairedComponentCount) -LogPath $LogPath
            Write-WULog -Message ("Pending Reboot: {0}" -f $summary.PendingReboot) -LogPath $LogPath
            Write-WULog -Message 'Recommendations:' -LogPath $LogPath
            foreach ($rec in $summary.Recommendations) { Write-WULog -Message " - $rec" -LogPath $LogPath }
        } catch {}
    }

    return $summary
}

Set-Alias -Name Get-UpdateFailure -Value Get-UpdateFailureReport -Scope Local -ErrorAction SilentlyContinue