- Compress-Vhdx: Compress multiple VHDX files using the PowerShell cmdlet Optimize-VHD - Wed, Nov 17 2021
- Display the progress of long-running tasks in PowerShell with Show-Progress instead of Write-Progress - Wed, Jul 28 2021
- Import Microsoft Defender Firewall rules from an Excel sheet with PowerShell in Windows 10 - Tue, Jul 6 2021
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.
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.
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):
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 }
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
Show-Progress not recognised as a command on my system with PS 5.1?
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
Seems like you may have forgotten the: Install-Module -Name Show-Progress in this article?
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