Public/Console/Show-CountdownTimer.ps1
function Show-CountdownTimer { param ( [Parameter(Position=0)] [ValidateRange(1, [Int32]::MaxValue)] [Int32]$Seconds = 0, [ValidateRange(1, [Int32]::MaxValue)] [Int32]$Milliseconds = 0, [ValidateRange(1, [Int32]::MaxValue)] [Int32]$Minutes = 0, [ValidateSet('Milliseconds', 'Seconds','SecondsDecimal','SecondsAndMilliseconds', 'MinutesDecimal','MinutesAndSeconds', 'MinutesAndSecondsAndMilliseconds', IgnoreCase = $true )] [String] $CountdownUnit = 'Seconds', [String] $FormatString = "Starting in [%TIME%]s...", [String] $FormatSeparator = ':', [Switch] $ShowSpinner ) if(($Seconds + $Milliseconds + $Minutes) -eq 0){ throw "You must pass in a value to either -Seconds -Milliseconds or -Minutes" } $spinner = @('|', '/', '-', '\') $spinnerPos = 0 $origpos = $host.UI.RawUI.CursorPosition [Console]::CursorVisible = $false $totalMilliseconds = ($Minutes * 60000) + ($Seconds * 1000) + $Milliseconds $runTime = $totalMilliseconds try { while($runTime -gt 0) { switch ($CountdownUnit) { 'Milliseconds' { $FormatStringNow = $FormatString -replace '\[%TIME%\]', "${runTime}" } 'SecondsDecimal' { $sec = Format-Milliseconds -Milliseconds $runTime -ConvertTo Seconds -DecimalPlaces 2 $FormatStringNow = $FormatString -replace '\[%TIME%\]', ('{0}' -f $sec) } 'SecondsAndMilliseconds' { $sec = [math]::Floor($runTime / 1000) -as [System.Int32] $mil = $runTime % 1000 $FormatStringNow = $FormatString -replace '\[%TIME%\]', ("{0:D2}$FormatSeparator{1:D3}" -f $sec, $mil) } 'MinutesDecimal' { $min = Format-Milliseconds -Milliseconds $runTime -ConvertTo Minutes -DecimalPlaces 2 $FormatStringNow = $FormatString -replace '\[%TIME%\]', ('{0}' -f $min) } 'MinutesAndSeconds' { $min = [math]::Floor($runTime / 60000) -as [System.Int32] $sec = [math]::Floor(($runTime % 60000) / 1000) -as [System.Int32] $FormatStringNow = $FormatString -replace '\[%TIME%\]', ("{0:D2}$FormatSeparator{1:D2}" -f $min, $sec) } 'MinutesAndSecondsAndMilliseconds' { $min = [math]::Floor($runTime / 60000) -as [System.Int32] $sec = [math]::Floor(($runTime % 60000) / 1000) -as [System.Int32] $mil = $runTime % 1000 $FormatStringNow = $FormatString -replace '\[%TIME%\]', ("{0:D2}$FormatSeparator{1:D2}$FormatSeparator{2:D3}" -f $min, $sec, $mil) } default { $remainingSeconds = [math]::Round($runTime / 1000, 2) -as [System.Int32] $FormatStringNow = $FormatString -replace '\[%TIME%\]', "${remainingSeconds}" } } if($ShowSpinner){ Write-Host (" {0} " -f $spinner[$spinnerPos%4]) -NoNewline Write-Host $FormatStringNow -NoNewline }else{ Write-Host $FormatStringNow -NoNewline } $host.UI.RawUI.CursorPosition = $origpos $spinnerPos += 1 if(($CountdownUnit -match 'Milliseconds') -or ($CountdownUnit -match 'SecondsDecimal')){ $runTime -= 50 # Decrement by 50 milliseconds for more granular countdown display Start-Sleep -Milliseconds 50 } else { $runTime -= 1000 # Decrement by 1000 milliseconds (1 second) Start-Sleep -Milliseconds 1000 } } } finally { Write-Host "" -NoNewline [Console]::CursorVisible = $true } } |