TheGeekery

The Usual Tech Ramblings

Powershell and Progress Feedback

We’re in the process of enabling a new password reset portal, which requires additional licensing features in Office 365. There is no “apply all” button in Office 365, so we have to do this via script to tens of thousands of user accounts. The problem with this is some form of feedback to the user running the script. PowerShell has some really handy built in features, such as a progress bar. It’s amazing how something so simple can make you feel a little better, and actively see how things are moving along. Progress bars in PowerShell are incredibly simple.

1
2
3
4
5
6
7
$count = 100

for($i = 1; $i -lt $count; $i++) {
       $pctComp = ($i /$count) * 100
       Write-Progress -Activity 'License assignment...' -Status $('{0}% complete' -f $pctComp) -PercentComplete $pctComp
       sleep 5
}

So this is very basic, all I’m doing is setting a counter to 100, and using a variable $i and incrementing the number. Then figuring out the percentage and using it to set the value in the progress bar. The sleep 5 is so we can actually see the progress bar in action. In our real world example, the count is based on the number of user objects, and no sleep was needed because it was actually doing work, unlike our sample code above.

Progress Bar

You can even get fancy with your progress bars, and actually have multiple progress bars. A use case example for this would be if you have a lot of operations on a single object, you might want to report the progress of that object. I’m just going to use a loop inside a loop for my example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$count = 100

for($i = 1; $i -lt $count; $i++) {
       $pctComp = ($i /$count) * 100
       Write-Progress -Activity 'License assignment...' -Status $('{0}% complete' -f $pctComp) -PercentComplete $pctComp -Id 1

       $innerCount = 50
       for ($m = 1; $m -lt $innerCount; $m++) {
             $innerPcgComp = ($m /$innerCount) * 100
             Write-Progress -Activity 'Inner loop' -Status $('{0}% complete' -f $innerPcgComp) -PercentComplete $innerPcgComp -ParentId 1
             sleep 1
      }

       sleep 2
}

In this example, notice how I use a -id and on the inner loop use -parentid. With these, the second progress bar becomes indented as a child of the first progress bar. You can keep going through multiple layers if you feel you want to, or you can have multiple parent loops and multiple child loops.

Progress Bar2

Your status messages don’t have to show the percentage either, they can be messages relating to the location in code. Here is another example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$count = 100

for($i = 1; $i -lt $count; $i++) {
       $pctComp = ($i /$count) * 100
       Write-Progress -Activity 'License assignment...' -Status $('{0}% complete' -f $pctComp) -PercentComplete $pctComp -Id 1

       Write-Progress -Activity 'Inner Loop' -Status 'Starting Inner Loop' -PercentComplete 1 -ParentId 1 -Id 2

       sleep 2

       Write-Progress -Activity 'Inner Loop' -Status 'Doing some other action' -PercentComplete 5 -ParentId 1 -Id 2

       sleep 2

       Write-Progress -Activity 'Inner Loop' -Status 'Doing something else' -PercentComplete 15 -ParentId 1 -Id 2

       sleep 2

       Write-Progress -Activity 'Inner Loop' -Status 'jumping waaaay up there' -PercentComplete 95 -ParentId 1 -Id 2

       sleep 2

       Write-Progress -Activity 'Inner Loop' -Status 'Finishing' -PercentComplete 100 -ParentId 1 -Id 2

       sleep 2
}

Progress Bar3

Progress Bar4

Sometimes it’s the simple things that we can add to a script that gives a whole lot of feedback to the user running it. If I’d not done a simple progress bar, we’d be clueless as to the progress of the script running against 45,000 users, and as the script took hours to run, some form of feedback is critical.

What other methods of feedback do you guys use? Have you used progress bars in a different fashion? Let me know.

Comments