Private/Write-CISProgress.ps1
|
if (-not $script:CISProgressTimes) { $script:CISProgressTimes = [System.Collections.Generic.List[double]]::new() } if (-not $script:CISProgressLastCheck) { $script:CISProgressLastCheck = $null } function Write-CISProgress { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Activity, [Parameter()] [string]$Status = 'Processing...', [Parameter()] [int]$PercentComplete = -1, [Parameter()] [int]$Current = 0, [Parameter()] [int]$Total = 0 ) if ($Total -gt 0 -and $Current -gt 0) { $PercentComplete = [math]::Min(100, [math]::Round(($Current / $Total) * 100)) $Status = "[$Current/$Total] $Status" } # Track timing for ETA estimation $now = [DateTime]::UtcNow if ($script:CISProgressLastCheck) { $elapsed = ($now - $script:CISProgressLastCheck).TotalSeconds $script:CISProgressTimes.Add($elapsed) # Sliding window: keep only the last 20 samples for ETA accuracy while ($script:CISProgressTimes.Count -gt 20) { $script:CISProgressTimes.RemoveAt(0) } } $script:CISProgressLastCheck = $now $eta = '' if ($script:CISProgressTimes.Count -ge 3 -and $Current -lt $Total) { $avgTime = ($script:CISProgressTimes | Measure-Object -Average).Average $remaining = ($Total - $Current) * $avgTime if ($remaining -ge 60) { $eta = " (~$([math]::Ceiling($remaining / 60)) min remaining)" } else { $eta = " (~$([math]::Ceiling($remaining))s remaining)" } } $progressParams = @{ Activity = "CIS Azure Benchmark - $Activity" Status = "${Status}${eta}" } if ($PercentComplete -ge 0) { $progressParams.PercentComplete = $PercentComplete } Write-Progress @progressParams } |