functions/Write-AnsiProgress.ps1
Function Write-ANSIProgress { [cmdletbinding()] [alias("wap")] [OutputType("None","String")] Param ( [Parameter( Position = 0, Mandatory, ValueFromPipeline, HelpMessage = "Enter a percentage in decimal value like .25" )] [ValidateScript({$_ -gt 0 -AND $_ -le 1})] [double]$PercentComplete, [Parameter(HelpMessage = "Specify an ANSI escape sequence or a PSStyle setting for the progress bar color.")] [string]$ProgressColor = "$([char]27)[38;5;51m", [Parameter(HelpMessage = "Specify what shape to use for the progress bar.")] [ValidateSet("Box", "Block", "Circle")] [string]$BarSymbol = "Box", [Parameter(HelpMessage = "Specify the cursor position")] [System.Management.Automation.Host.Coordinates]$Position = $host.UI.RawUI.CursorPosition, [Parameter(HelpMessage = "Write to the host not the pipeline")] [switch]$ToHost ) Begin { Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)" #Validate the progress color. The normal parameter validation techniques don't like the regex pattern if ( -Not [regex]::IsMatch($ProgressColor, "$([char]27)\[\d+[\d;]+m")) { Throw "You entered an invalid ANSI escape sequence" } #the closing ANSI sequence $end = "$([char]27)[0m" #a length of 50 is the max or 100% $max = 50 Switch ($BarSymbol) { "box" { $block = [char]9632 } "block" { $block = [char]9608} "circle" { $block = [char]9679 } } #these values will be used to set the progress bar position $x = $position.x #modified July 12, 2024 to not add an extra line $y = $position.y #+ 1 #may need to insert a line in case we are at the bottom of a console or terminal screen if ($env:WT_SESSION -AND ($position.y + 1 -ge $host.UI.RawUI.BufferSize.Height)) { #Write-Output "`n" Write-Host "`n" } } #begin Process { If ($host.Name -match "PowerShell ISE") { Write-Warning "This command will not work in the PowerShell ISE." #bail out return } Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] $PercentComplete %" [int]$len = $max * $PercentComplete #get current cursor position if in Windows Terminal if ($env:WT_SESSION -AND ($position.y + 1 -ge $host.UI.RawUI.BufferSize.Height)) { $y = $host.UI.RawUI.CursorPosition.Y-1 } [System.Console]::SetCursorPosition($x, $y) #align and pad the percentage value $pct = "$($percentComplete*100)%".PadLeft(4) #Modified June 27, 2024 to write to the host so progress isn't part of any command output if ($ToHost) { Write-Host "$pct $ProgressColor$($($Block.ToString())*$len)$End" } else { Write-Output "$pct $ProgressColor$($($Block.ToString())*$len)$End" } } #process End { Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)" } #end } #close Write-ANSIProgress |