Prof. Powershell

PowerShell's Write-Progress Explored

Jeffery Hicks breaks down how to use the Write-Progress cmdlet.

The last few lessons have been on displaying status messages in your PowerShell scripts and functions. There is also a built-in cmdlet that doesn't get used as much as it should so I thought I'd give you a quick introduction to Write-Progress.

This cmdlet has been around from the very beginning of PowerShell. You've probably seen something like this before:

[Click on image for larger view.]  Figure 1. A Write-Progress Sample

To use the cmdlet you are required to specify an Activity. You can also specify a status, what the script is currently doing and a percentage complete progress bar. Or you can specify seconds remaining which I find harder to calculate, as least for the scripts I write.

Using the scenario from the last lesson to get top level folder usage, I'm going to use Write-Progress. Here's my path.

$Path = "C:\Scripts"

I like using a hash table of parameter values that I can splat to Write-Progress. Personally I find it easier to read and troubleshoot the script.

$progParam=@{
Activity = "Directory Usage Analysis"
CurrentOperation=$path
Status="Querying top level folders"
PercentComplete=0
}

I'm going to go ahead and use all the options. Activity is the only required parameter. Splatting the parameters gets me started.

 

Write-Progress @progParam

Now to get top level folders. Again, I've arbitrarily thrown in some Start-Sleep commands to make it easier to see the changes in the progress bar.

$top = Get-ChildItem -Path $path -Directory
Start-Sleep -Milliseconds 300

As with my previous articles, I find it easier to use Write-Progress when using ForEach, primarily because I know in advance how many items I have to process so I can calculate a percentage.

#initialize a counter
$i=0

foreach ($folder in $top) {

#calculate percentage
$i++
[int]$pct = ($i/$top.count)*100

 $progParam.CurrentOperation ="Measuring size: $($folder.Name)"
$progParam.Status="Analyzing"
$progParam.PercentComplete = $pct

 Write-Progress @progParam

 start-sleep -Milliseconds 100
$stats = Get-ChildItem -path $folder -Recurse -File |
Measure-Object -Property Length -Sum -Average
[pscustomobject]@{
Path=$folder.Name
Files = $stats.count
SizeKB = [math]::Round($stats.sum/1KB,2)
Avg = [math]::Round($stats.average,2)
}
} #foreach

This is essentially the same code I used last time, except each time through I'm updating the hash table and splatting the new table to Write-Progress. Here's what it looks like (video).

For long running scripts or functions using Write-Progress is very helpful. You can get very creative with this cmdlet so I encourage you to take the time to read the full cmdlet help and examples. Next time, we'll look at one more status progress example.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular