Copy and paste this sample script and modify as needed for your environment:
<# .SYNOPSIS Â Â Shows the current status of the Secure Boot rollout orchestrator.
.DESCRIPTION   Provides real-time visibility into the rollout progress:   - Current wave number and devices targeted   - Devices updated vs pending   - Blocked buckets requiring attention   - Recent activity log   - Dashboard link      Run this anytime to see how the rollout is progressing.
.PARAMETER ReportBasePath   Path to the report/state directory used by the orchestrator
.PARAMETER ShowLog   Display recent log entries (last 50 lines)
.PARAMETER ShowBlocked   Show details of blocked buckets
.PARAMETER ShowWaves   Show wave history with device counts
.PARAMETER Watch   Continuously refresh status every N seconds
.PARAMETER OpenDashboard   Open the latest HTML dashboard in browser
.EXAMPLE Â Â .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports"
.EXAMPLE Â Â .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports" -Watch 30
.EXAMPLE Â Â .\Get-SecureBootRolloutStatus.ps1 -ReportBasePath "C:\SecureBootReports" -OpenDashboard #>
[CmdletBinding()] param( Â Â [Parameter(Mandatory = $true)] Â Â [string]$ReportBasePath, Â Â Â Â Â [Parameter(Mandatory = $false)] Â Â [switch]$ShowLog, Â Â Â Â Â [Parameter(Mandatory = $false)] Â Â [switch]$ShowBlocked, Â Â Â Â Â [Parameter(Mandatory = $false)] Â Â [switch]$ShowWaves, Â Â Â Â Â [Parameter(Mandatory = $false)] Â Â [int]$Watch = 0, Â Â Â Â Â [Parameter(Mandatory = $false)] Â Â [switch]$OpenDashboard )
$ErrorActionPreference = "Stop" $DownloadUrl = "https://aka.ms/getsecureboot" $DownloadSubPage = "Deployment and Monitoring Samples"
# Note: This script has no dependencies on other scripts. # For the complete toolset, download from: $DownloadUrl -> $DownloadSubPage
# ============================================================================ # HELPER FUNCTIONS # ============================================================================
function ConvertTo-Hashtable {   param([Parameter(ValueFromPipeline = $true)]$InputObject)   process {     if ($null -eq $InputObject) { return @{} }     if ($InputObject -is [System.Collections.IDictionary]) { return $InputObject }     if ($InputObject -is [PSCustomObject]) {       $hash = @{}       foreach ($prop in $InputObject.PSObject.Properties) {         $hash[$prop.Name] = ConvertTo-Hashtable $prop.Value       }       return $hash     }     if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {       return @($InputObject | ForEach-Object { ConvertTo-Hashtable $_ })     }     return $InputObject   } }
function Show-Status {   $stateDir = Join-Path $ReportBasePath "RolloutState"   $rolloutStatePath = Join-Path $stateDir "RolloutState.json"   $blockedBucketsPath = Join-Path $stateDir "BlockedBuckets.json"      Clear-Host   Write-Host ""   Write-Host ("=" * 80) -ForegroundColor Cyan   Write-Host "  SECURE BOOT ROLLOUT STATUS" -ForegroundColor Cyan   Write-Host "  $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Gray   Write-Host ("=" * 80) -ForegroundColor Cyan   Write-Host ""      # Check if orchestrator task is running   $task = Get-ScheduledTask -TaskName "SecureBoot-Rollout-Orchestrator" -ErrorAction SilentlyContinue   if ($task) {     $taskState = $task.State     $color = if ($taskState -eq "Running") { "Green" } elseif ($taskState -eq "Ready") { "Yellow" } else { "Red" }     Write-Host "Scheduled Task: " -NoNewline     Write-Host $taskState -ForegroundColor $color   } else {     Write-Host "Scheduled Task: " -NoNewline     Write-Host "Not Installed" -ForegroundColor Gray   }      # Load rollout state   if (-not (Test-Path $rolloutStatePath)) {     Write-Host ""     Write-Host "No rollout state found. Orchestrator may not have started yet." -ForegroundColor Yellow     Write-Host "State path: $rolloutStatePath" -ForegroundColor Gray     return   }      $state = Get-Content $rolloutStatePath -Raw | ConvertFrom-Json | ConvertTo-Hashtable      Write-Host ""   Write-Host "ROLLOUT PROGRESS" -ForegroundColor Yellow   Write-Host ("-" * 40)      $status = $state.Status   $statusColor = switch ($status) {     "Completed" { "Green" }     "InProgress" { "Cyan" }     "NotStarted" { "Gray" }     default { "White" }   }      Write-Host "Status:        " -NoNewline   Write-Host $status -ForegroundColor $statusColor   Write-Host "Current Wave:     $($state.CurrentWave)"   Write-Host "Total Targeted:    $($state.TotalDevicesTargeted)"   Write-Host "Total Updated:    $($state.TotalDevicesUpdated)"      if ($state.StartedAt) {     Write-Host "Started:       $($state.StartedAt)"   }   if ($state.LastAggregation) {     Write-Host "Last Check:      $($state.LastAggregation)"   }   if ($state.CompletedAt) {     Write-Host "Completed:      $($state.CompletedAt)" -ForegroundColor Green   }      # Show progress bar   if ($state.TotalDevicesTargeted -gt 0) {     $pct = if ($state.TotalDevicesUpdated -and $state.TotalDevicesTargeted) {       [math]::Round(($state.TotalDevicesUpdated / $state.TotalDevicesTargeted) * 100, 1)     } else { 0 }          Write-Host ""     Write-Host "Progress: " -NoNewline     $barWidth = 40     $filled = [math]::Floor($barWidth * $pct / 100)     Write-Host "[" -NoNewline     Write-Host ("█" * $filled) -ForegroundColor Green -NoNewline     Write-Host ("░" * ($barWidth - $filled)) -ForegroundColor DarkGray -NoNewline     Write-Host "] $pct%"   }      # Blocked buckets summary   if (Test-Path $blockedBucketsPath) {     $blocked = Get-Content $blockedBucketsPath -Raw | ConvertFrom-Json | ConvertTo-Hashtable     if ($blocked.Count -gt 0) {       Write-Host ""       Write-Host "BLOCKED BUCKETS: " -NoNewline -ForegroundColor Red       Write-Host "$($blocked.Count) buckets need attention" -ForegroundColor Red              if ($ShowBlocked) {         Write-Host ""         foreach ($key in $blocked.Keys) {           $info = $blocked[$key]           Write-Host "  ► $key" -ForegroundColor Red           Write-Host "   Reason: $($info.Reason)" -ForegroundColor Gray           Write-Host "   Device: $($info.FailedDevice)" -ForegroundColor Gray           Write-Host "   Since:  $($info.BlockedAt)" -ForegroundColor Gray         }       } else {         Write-Host "  Run with -ShowBlocked for details" -ForegroundColor Gray       }     }   }      # Wave history   if ($ShowWaves -and $state.WaveHistory -and $state.WaveHistory.Count -gt 0) {     Write-Host ""     Write-Host "WAVE HISTORY" -ForegroundColor Yellow     Write-Host ("-" * 40)          foreach ($wave in $state.WaveHistory) {       Write-Host "Wave $($wave.WaveNumber): " -NoNewline -ForegroundColor Cyan       Write-Host "$($wave.DeviceCount) devices" -NoNewline       Write-Host " - $($wave.StartedAt)" -ForegroundColor Gray     }   }      # Latest dashboard   $latestAggregation = Get-ChildItem -Path $ReportBasePath -Directory -Filter "Aggregation_*" -ErrorAction SilentlyContinue |     Sort-Object Name -Descending |     Select-Object -First 1      if ($latestAggregation) {     $dashboard = Get-ChildItem -Path $latestAggregation.FullName -Filter "*Dashboard*.html" -ErrorAction SilentlyContinue |       Select-Object -First 1          if ($dashboard) {       Write-Host ""       Write-Host "LATEST DASHBOARD" -ForegroundColor Yellow       Write-Host $dashboard.FullName -ForegroundColor Gray              if ($OpenDashboard) {         Start-Process $dashboard.FullName       }     }   }      # Recent log   if ($ShowLog) {     $logFile = Get-ChildItem -Path $stateDir -Filter "Orchestrator_*.log" -ErrorAction SilentlyContinue |       Sort-Object Name -Descending |       Select-Object -First 1          if ($logFile) {       Write-Host ""       Write-Host "RECENT LOG" -ForegroundColor Yellow       Write-Host ("-" * 40)              Get-Content $logFile.FullName -Tail 20 | ForEach-Object {         if ($_ -match '\[ERROR\]') {           Write-Host $_ -ForegroundColor Red         } elseif ($_ -match '\[WARN\]') {           Write-Host $_ -ForegroundColor Yellow         } elseif ($_ -match '\[OK\]') {           Write-Host $_ -ForegroundColor Green         } elseif ($_ -match '\[WAVE\]') {           Write-Host $_ -ForegroundColor Cyan         } else {           Write-Host $_ -ForegroundColor Gray         }       }     }   }      Write-Host ""   Write-Host ("-" * 80) -ForegroundColor DarkGray      if (-not $ShowLog -or -not $ShowWaves -or -not $ShowBlocked) {     Write-Host "Options: -ShowLog | -ShowWaves | -ShowBlocked | -OpenDashboard | -Watch 30" -ForegroundColor DarkGray   } }
# ============================================================================ # MAIN # ============================================================================
if (-not (Test-Path $ReportBasePath)) {   Write-Host "Report path not found: $ReportBasePath" -ForegroundColor Red   exit 1 }
if ($Watch -gt 0) {   Write-Host "Watching status every $Watch seconds. Press Ctrl+C to stop." -ForegroundColor Cyan   while ($true) {     Show-Status     Start-Sleep -Seconds $Watch   } } else {   Show-Status } Â