Skip to content

Instantly share code, notes, and snippets.

@scriptingstudio
Last active July 27, 2026 15:28
Show Gist options
  • Select an option

  • Save scriptingstudio/751b230a596031db1d5bd1b22ad467b7 to your computer and use it in GitHub Desktop.

Select an option

Save scriptingstudio/751b230a596031db1d5bd1b22ad467b7 to your computer and use it in GitHub Desktop.
Yet another PowerShell inline progress bar
function Show-Progress {
param (
[scriptblock] $scriptblock,
[int] $width,
[consolecolor] $color,
[string] $type, # growth | fill | bounce | tide
[switch] $passthru
)
if (-not $scriptblock) {return}
if ($width -lt 1) {$width = 10}
if ([Console]::CursorLeft + $width -ge [Console]::WindowWidth) {
return Measure-Command -Expression $scriptblock -ErrorAction 0
}
if ($type -notmatch 'growth|fill|bounce|tide') {$type = 'growth','fill','bounce','tide' | Get-Random}
$pipeUI = [hashtable]::Synchronized(@{})
$pipeUI.x,$pipeUI.y = [Console]::CursorLeft,[Console]::CursorTop
$pipeUI.width = $width
if ($null -ne $color) {$pipeUI.color = $color}
$pipeUI.type = $type
$rsjob = [runspacefactory]::CreateRunspace()
$rsjob.ApartmentState = "STA"
$rsjob.ThreadOptions = "ReuseThread"
$rsjob.Open()
$rsjob.SessionStateProxy.SetVariable("pipeUI", $pipeUI)
$pipeUI.psThread = [powershell]::Create().AddScript({
$start = [datetime]::now
$pipeUI.running = $true
$width = $pipeUI.width
$count = if ($pipeUI.type -eq 'tide') {0} else {1}
$dir = 1 # from left to rigth
$fill = '░'
$cursor = '▓'
$format = "{0,$(-$width-1)}"
$sleep = if ($pipeUI.type -eq 'bounce') {100} else {120}
[Console]::CursorVisible = $false
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$fg = [Console]::ForegroundColor
if ($pipeUI.color) {[Console]::ForegroundColor = $pipeUI.color}
while ($pipeUI.running) {
Start-Sleep -Milliseconds $sleep
if ($pipeUI.type -eq 'bounce') {
if ($dir -eq 1) {
[Console]::Write($fill*($count-1))
[Console]::Write($cursor)
[Console]::Write($fill*($width-$count))
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count++
if ($count -gt $width) {$count--; $dir = 0}
} else {
[Console]::Write($fill*($count-1))
[Console]::Write($cursor)
[Console]::Write($fill*($width-$count))
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count--
if ($count -eq 0) {$count++; $dir = 1}
}
} elseif ($pipeUI.type -eq 'tide') {
if ($dir -eq 1) {
[Console]::Write($cursor*$count)
[Console]::Write($fill*($width-$count))
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count++
if ($count -gt $width) {$count--; $dir = 0}
} else {
[Console]::Write($cursor*$count)
[Console]::Write($fill*($width-$count))
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count--
if ($count -eq -1) {$count++; $dir = 1}
}
} elseif ($pipeUI.type -eq 'growth') {
[Console]::Write($format,$cursor*$count)
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count++
if ($count -gt $width) {$count = 1}
} else { # fill
[Console]::Write($cursor*$count)
[Console]::Write($fill*($width-$count))
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
$count++
if ($count -gt $width) {$count = 1}
}
}
$pipeUI.runtime = [datetime]::now - $start
# cleanup
if ($pipeUI.type -eq 'growth') {
[Console]::Write($format,'⁠ '*$width)
} else {
[Console]::Write('⁠ '*$width)
}
if ([Console]::ForegroundColor -ne $fg) {[Console]::ForegroundColor = $fg}
[Console]::SetCursorPosition($pipeUI.x,$pipeUI.y)
[Console]::CursorVisible = $true
})
$pipeUI.psThread.Runspace = $rsjob
$pipeUI.handle = $pipeUI.psThread.BeginInvoke()
$null = & $scriptblock
$pipeUI.running = $false
while (-not $pipeUI.handle.IsCompleted) {[System.Threading.Thread]::Sleep(40)}
$null = $pipeUI.psThread.EndInvoke($pipeUI.handle)
$pipeUI.psThread.Runspace.Close()
$pipeUI.psThread.Runspace.Dispose()
$pipeUI.psThread.Dispose()
$pipeUI.psThread = $null
if ($passthru) {$pipeUI.runtime}
} # END Show-Progress
Write-Host 'Long running script... ' -NoNewline
(Show-Progress {Start-Sleep -Milliseconds 7388} -passthru -type bounce -color Yellow).TotalMilliseconds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment