The Show-Progress function provides a nice, compact way to display the progress of longer-running tasks in PowerShell. You can use it as a replacement for Write-Progress. While this has the advantage of being a "native" cmdlet with a few options to customize the progress of tasks, it occupies a bit of real estate in the PowerShell window (the upper portion of the console), sometimes hiding interesting information. The Show-Progress function is only a single line of text, at the current cursor position, and does not hide any output or status messages from other commands.

The progress is displayed as a progress bar along with the completion percentage for the currently running task. You can also provide a custom title for the task.

Prerequisites ^

The only prerequisite for the function is Windows PowerShell 5.1, which is the version shipped in any supported version of Windows. It also works with PowerShell 7. I did not test the function with older PowerShell versions.

Show-Progress can take advantage of other PowerShell modules loaded in the current session. For instance, if you have the PowerShell module for WSUS, you can display the WSUS server's progress downloading approved updates (an example of that is included in the next section).

Usage examples ^

You can use Get-Help to view the help for the function or use the switch -Examples to see some usage examples from the function's native help. Of course, the best way to test and understand Show-Progress is to put it to work. Let's look at a few usage scenarios.

Basic usage

Using Show-Progress without providing any parameters displays a simple progress bar for 100 seconds. While it looks nice, it is not particularly interesting.

Basic usage running in PowerShell 7

Basic usage running in PowerShell 7

Download progress in WSUS

Let's look at a more interesting scenario: showing a WSUS server's progress downloading approved updates from an upstream server. For better-looking code, we'll use splatting instead of a very long one-line command:

$WsusDownload = @{
    'PercentComplete' = ($WsusServer.GetContentDownloadProgress()).DownloadedBytes
    'Total' = ($WsusServer.GetContentDownloadProgress()).TotalBytesToDownload
    'Activity' = "Downloading WSUS Updates"
    'Refresh' = 5
    }
Show-Progress @WsusDownload 

This shows the download progress of the WSUS server. The progress bar and completion percentage are updated every 5 seconds.

WSUS downloads in progress

WSUS downloads in progress

Once completed, the progress bar looks like this, and the cursor becomes active again (unless this is part of a script and more commands follow):

WSUS downloads complete

WSUS downloads complete

Mass changes to a collection of users

Here, we update an entire OU of users (in this case, we change the description for our OU of Redirected Users) and use Show-Progress to display the overall progress.

$OU = "OU=RedirectedUsers,OU=Users,OU=Prod,DC=ha,DC=lab"
$AllUsers = Get-ADUser -Filter * -SearchBase $OU
$Complete = 0

foreach ($User in $AllUsers) {
    $User | Set-ADUser -Description "Moved from Vancouver"
    $Complete +=1
    Show-Progress -PercentComplete $Complete -Total $AllUsers.count -Activity "Setting Description" -RefreshInterval 5
    } 
Mass editing users from an OU

Mass editing users from an OU

The Show-Progress function ^

The complete code for the function is below. To have it available every time, you can include it in your PowerShell profile script or in a module.

Subscribe to 4sysops newsletter!

function Show-Progress {

<#
.SYNOPSIS
    Displays the completion status for a running task.
.DESCRIPTION
    Show-Progress displays the progress of a long-running activity, task, 
    operation, etc. It is displayed as a progress bar, along with the 
    completed percentage of the task. It displays on a single line (where 
    the cursor is located). As opposed to Write-Progress, it doesn't hide 
    the upper block of text in the PowerShell console.
.PARAMETER Activity
    A label you can assign to the current task. Normally, you'd put a relevant 
    description of what you're trying to accomplish (like "Restarting computers", 
    or "Downloading Updates").
.PARAMETER PercentComplete
    Percentage to evaluate against the parameter total. It can be a number of 
    members processed from a collection, a partial download, the current number of 
    completed tasks, etc.
.PARAMETER Total
    This is the number to evaluate against. It can be the number of users in a 
    group, total number of bytes to download, total number of tasks to execute, etc.
.PARAMETER RefreshInterval
    Amount of time between two 'refreshes' of the percentage complete and update
    of the progress bar. The default refresh interval is 1 second.
.EXAMPLE
    Show-Progress
    Without any arguments, Show-Progress displays a progress bar for 100 seconds.
    If no value is provided for the Activity parameter, it will simply say 
    "Current Task" and the completion percentage.
.EXAMPLE
    Show-Progress -PercentComplete ($WsusServer.GetContentDownloadProgress()).DownloadedBytes -Total ($WsusServer.GetContentDownloadProgress()).TotalBytesToDownload -Activity "Downloading WSUS Updates"
    Displays a progress bar while WSUS downloads updates from an upstream source.
.NOTES
    Author: Emanuel Halapciuc
    Last Updated: July 5th, 2021
#>


 Param(
 [Parameter()][string]$Activity="Current Task",
 [Parameter()][ValidateScript({$_ -gt 0})][long]$PercentComplete=1,
 [Parameter()][ValidateScript({$_ -gt 0})][long]$Total=100,
 [Parameter()][ValidateRange(1,60)][int]$RefreshInterval=1
 )

Process {    

    #Continue displaying progress on the same line/position
    $CurrentLine = $host.UI.RawUI.CursorPosition

    #Width of the progress bar
    if ($host.UI.RawUI.WindowSize.Width -gt 70) { $Width = 50 }
    else { $Width = ($host.UI.RawUI.WindowSize.Width) -20 }
    if ($Width -lt 20) {"Window size is too small to display the progress bar";break}

    $Percentage = ($PercentComplete / $Total) * 100

    #Write-Host -ForegroundColor Magenta "Percentage: $Percentage"

    for ($i=0; $i -le 100; $i += $Percentage) {
        
        $Percentage = ($PercentComplete / $Total) * 100
        $ProgressBar = 0

        $host.UI.RawUI.CursorPosition = $CurrentLine
        
        Write-Host -NoNewline -ForegroundColor Cyan "["

        while ($ProgressBar -le $i*$Width/100) {
            Write-Host -NoNewline "="
            $ProgressBar++
            }

        while (($ProgressBar -le $Width) -and ($ProgressBar -gt $i*$Width/100)  ) {
            Write-Host -NoNewline " "
            $ProgressBar++
            }        

        #Write-Host -NoNewline $i

        Write-Host -NoNewline -ForegroundColor Cyan "] "
        Write-Host -NoNewline "$Activity`: "
        
        Write-Host -NoNewline "$([math]::round($i,2)) %, please wait"
        
        Start-Sleep -Seconds $RefreshInterval
        #Write-Host ""

        } #for


    #
    $host.UI.RawUI.CursorPosition = $CurrentLine
    
    Write-Host -NoNewline -ForegroundColor Cyan "["
    while ($end -le ($Width)) {
        Write-Host -NoNewline -ForegroundColor Green "="
        $end += 1
        }

    Write-Host -NoNewline -ForegroundColor Cyan "] "
    Write-Host -NoNewline "$Activity complete                    "
    #>
    } #Process

} #function
+3
4 Comments
  1. Jonathan Seymour 2 months ago

    Show-Progress not recognised as a command on my system with PS 5.1?

    0

    • Author

      Hi, Jonathan.
      Well, before it's recognised, you need to copy/paste the code from this article in your PowerShell window. To always have it available, you can save it as a script and reference it, you can copy it in your PowerShell Profile, or you can save it in a (new or existing) PowerShell module.
      I hope this helps. Emanuel

      +2

      • _MikeC 2 months ago

        Seems like you may have forgotten the: Install-Module -Name Show-Progress in this article?

        +1

  2. Author

    Hi, Mike.
    I didn't quite forget it; it's just a function, not a module. If you save it as a PSM1 file, then you can install/ reference it. But I wouldn't create a dedicated module for such a small function. My vanity doesn't go that far. 🙂

    Cheers! Emanuel

    0

Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account