Adding a progress bar to your PowerShell scripts

Those of you who know me, or who know my work, know that I live and breathe PowerShell. As such, I tend to build a lot of PowerShell scripts that automate various tasks. But some tasks can take quite a while to complete, and you may wonder whether a script is still running or has gotten hung up. One way that you can gain more insights into your PowerShell scripts is by incorporating a progress bar.

Let me show you how it works.

You can use the Write-Progress cmdlet to add a progress bar to any PowerShell script. Microsoft has provided a super simple script to show how this cmdlet works.

Here is the script:

for ($i = 1; $i -le 100; $i++ )
{
Write-Progress -Activity "Search in Progress" -Status "$i% Complete:" -PercentComplete $i
Start-Sleep -Milliseconds 250
}

The first line of the script sets up a loop. The loop starts with the $i variable set to 1 and each loop cycle increases the value of $i by 1 ($i++). The loop ends when $i reaches 100.

The Write-Progress cmdlet provides includes three parameters. The first is the activity. The activity is just the text that is displayed to the left of the progress bar. In this case, that text says Search in Progress. You can see the text in the figure below.


This is what the progress bar looks like.

The second parameter is the status. The status typically displays the percentage of the task that has completed. You can see in the figure above that the phrase “29% Complete” is displayed on the progress bar. This text was put there by the Status parameter.

The third parameter is the PercentComplete parameter. This is the parameter that tells the progress bar how far the task has progressed so that PowerShell knows how much bar to display.

The last line of the script is the Start-Sleep line. This line introduces a 250 millisecond delay each time that the script loops. This delay only exists to make the script run slowly enough for you to be able to see the progress bar inch across the screen. In a normal script you would not typically introduce a delay.

So with that said, let’s take a look at how you might add a progress bar to an existing script. A while back, I wrote a simple script that read a list of virtual machines from a CSV file and then used the Get-VM cmdlet to display the requested virtual machine. For the sake of demonstration, I have added a progress bar to this script. Here is what the script looks like:

$List = Import-CSV C:\Scripts\VMs.csv -Header 'Name'
$TotalItems=$List.Count
$CurrentItem = 0
$PercentComplete = 0
ForEach($VM in $List)
{
Write-Progress -Activity "Checking Virtual Machines" -Status "$PercentComplete% Complete:" -PercentComplete $PercentComplete
$Name = $VM.Name
Get-VM -Name $Name
$CurrentItem++
$PercentComplete = [int](($CurrentItem / $TotalItems) * 100)
Start-Sleep -Milliseconds 2500
}

Before I walk you through the script, let me show you the script’s output.


This is what the script does.

The first thing that you need to know about this output is that I have edited the screen capture for the sake of demonstration. Normally, the progress bar goes all the way to 100%, disappears, and then the output is revealed. However, I took a screen capture of the progress bar and combined it with a screen capture of the output so that you could see all of the elements. In real life, the progress bar and the virtual machines are not shown on the screen simultaneously.

The first line of code reads the list of virtual machines from the CSV file. The virtual machines are stored in a variable named $List. The second line creates a variable called $TotalItems. This variable reflects the total number of items in $List (the total number of virtual machines). I use the total item count later on when calculating a percentage.

Next, I create a variable called $CurrentItem. It reflects which list item I am working with (virtual machine 1, virtual machine 2, etc.) I also created a variable called $PercentComplete and set it to 0 since the script has yet to complete any actual work at this point.

The following line defines the loop. Here I am creating a For Each loop that looks at each virtual machine in the $List of virtual machines.

The first step in the loop is to display the progress bar. As you can see in the previous screen capture, I am using the text “Checking Virtual Machines” along with the percentage complete.

The next line retrieves the virtual machine name from the list. The subsequent line uses the Get-VM cmdlet to get Hyper-V to display some basic details for the specified virtual machine.

Next, I increase the $CurrentItem number by 1 ($CurrentItem++) and then I calculate the percentage of the task that has been completed. This percentage is simply the current item number divided by the total number of items (in this case, virtual machines). I then multiply the entire thing by 100 so that it will be displayed as a percentage and not a decimal number. I then use [int] to display the result as an integer. You will notice in the screen capture that the task is 33% complete, and not 33.333333% complete. It is the [int] that causes the percentage to be expressed as a whole number.

Finally, I use the Start-Sleep cmdlet to inject a delay between each virtual machine. Again, you don’t have to do this in real life. I just needed the delay so that the script would run slowly enough that I could get a screen capture of the progress bar.

The really great thing about working with progress bars in PowerShell is that you can get increasingly complex with them if you like. PowerShell 7.2 will allow you to use ANSI escape sequences to customize a progress bar’s appearance.

About The Author

3 thoughts on “Adding a progress bar to your PowerShell scripts”

Leave a Comment

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top