How To: PowerShell progress bars

Ever since I started learning PowerShell I have been a fan of various PowerShell “How To” guides. After learning so much from so many people I decided I should start my own to give back to the PowerShell community. I’ll be running a series of posts that re PowerShell “How to” guides that give examples of how to do certain things in PowerShell. For all of the How To Guide posts I am planning I will post a link to the code on GitHub at the start of the post. https://github.com/JordanTheITGuy/PowerShell/tree/master/BlogPosts/HowTo%20-%20Creating%20Progress%20Bars

PowerShell loops

To do anything with a PowerShell progress bar we need to be engaging in a process or a loop. In this guide we will be working with the Do/Until loop. As a quick reminder the Do/Until Loop does something until a condition is $true. So for example.

Do {
$Count++
write-verbose -message "$($Count)" -verbose
}Until($Count -eq 10)
$count = $null

This will result in an output of counting from 1 – 10. Simple enough Do something until done.

PowerShell Progress Bar

While the example above writes a verbose message to the screen that’s really simply but not useful. Using the same code as a base we can add the “Write-Progress” cmdlet to create a simple progress bar.

Do{
    $Count++
    Write-Progress -Activity "Counting to 10" -Status "Running..." -PercentComplete $($count * 10) -CurrentOperation "Current number is $($count)"
    Start-Sleep -Seconds 1
}until($count -eq 10)
$count = $null

Note: If you run this in VSCode you need to make sure that you change the PowerShell terminal to “PowerShell” not “integrated” this is currently under development. In the image below you will see point 1 for where to change to PowerShell and the progress bar at point 2.

See GitHub for Details

Now this code isn’t very useful. However, it shows how we can create a progress bar to track the actions of a loop. The logic in this loop isn’t great though as doesn’t track “Real” numbers. Lets try something more interesting using a for each loop to move files.

$Contents = Get-ChildItem -Path "C:\Users\jbenz001\Desktop\Folder2"
$Destination = "C:\Users\jbenz001\Desktop\Folder1"
foreach($Item in $Contents){
    Move-Item -path $Item.FullName -Destination $Destination
    [int]$currentItem = [array]::indexof($Contents,$Item)
    Write-Progress -Activity "Moving files" -Status "Currently Moving - $($Item.Name) - File $($currentItem) of $($Contents.Count - 1) $([math]::round((($currentItem + 1)/$Contents.Count),2) * 100)% " -PercentComplete $([float](($currentItem + 1)/$Contents.Count) * 100)
    Start-Sleep -Seconds 1
}

What is this really doing?

This is more advanced without being totally crazy. The above code creates a progress bar and updates it based on the number of files being moved. Here is a quick step by step breakdown of the actions taking place.

  • Get all the files in Folder2.
  • Set the destination we would like to move those items to $Destination
  • For each ITEM that we retrieved from the folder.
  • Move the item from the source location to the destination
  • Using the Item – analyze the array and find its index to track where we are in terms of completion.
  • Write our progress to the screen
    • Using the “$CurrentItem” track how far in we are, and calculate what percent of the files we have moved.
    • Display that percentage status in the status message bar.
    • Display that percentage as the percentage we have moved.

If you are looking closely you will notice there is a weird “+ 1” in the script. This is just to deal with the fact that array’s start counting at 0.

If you take a close look at the blue progress bar you can see its displaying the file that is being worked with. This is just basic string manipulation and some simple math. It also waits one second to ensure you can read it. I’m not going to explain the exact “math” and such that’s done in the function suffice to say it calculates percentiles based on files moved.

Closing remarks

Hopefully you enjoyed reading about how to create a PowerShell progress bar. In the end it’s nothing more than a “Write-Progress” cmdlet with some extra information. There are many ways to generate that data as the loop is executing. Find the one that works for you and go from there. Let me know if you want to see more guides like this.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: