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 }  

Need more help?

Want more options?

Explore subscription benefits, browse training courses, learn how to secure your device, and more.