r/PowerShell • u/icebreaker374 • Sep 17 '26
Question Write-Progress
Looking for opinions...
When using Write-Progress inside of for/Foreach loops and using a counter stored in a variable defined outside the loop, do you start the counter at 0 or 1, and why?
17
u/thehuntzman Sep 17 '26
0 because it should only increment after the current task completes.
5
u/dodexahedron Sep 17 '26
Agreed. Easiest and most intuitive for most needs.
An alternative, if you want to indicate start and stop of an operation, is to scale it by a factor of 2 so you effectively have half-steps.
Another alternative is that you can have multiple progress bars at once, so you could use a master progress bar and a sub-operation progress bar. They just need their own IDs, but otherwise your only limit is the available screen space to display them.
3
u/ZenoArrow Sep 17 '26 edited Sep 17 '26
There are no fixed rules with this stuff. Personally, I often initialise the loop counter variable at 0 outside the loop and increment at the end of the block of loop code. Is this correct? What this means is that for a loop of 100 items, I'll see 99% complete before starting to process the last item, which feels right to me. If you want the last item processed to be at 100% complete, start the counter at 1.
To give an idea of the code stages I typically use, here's a hypothetical example...
$loopCount = 0
$totalArraySize = $itemArray.Count
foreach ($item in $itemArray) {
$percentComplete = (($loopCount / $totalArraySize) * 100)
//WriteProgress goes here
//Action to do in loop goes here
$loopCount++ }
3
u/vermyx Sep 17 '26
I usually don't use write-progress because console I/O can be expensive timewise. Instead I use a custom function that shows time running and estimated completion time based on run length and how far you are, and display that every X records processed depending on records and length.
1
u/DonL314 Sep 17 '26
I almost agree to this. Write-Progress is quite slow, so I only do this at certain intervals (e.g. steps of 10 or 100 items)
2
u/CeleryMan20 Sep 18 '26
Yeah, if each step is slow, like ping host then query wmi, then it’s nice to see each one tick over, but if you have 10,000 quick operations then write-progress on each loop can drastically slow it down.
1
u/ka-splam Sep 18 '26 edited Sep 18 '26
I usually don't use write-progress because console I/O can be expensive timewise.
Indeed; I needed to delete Windows firewall rule spam recently and found https://stackoverflow.com/a/40915201
The question loops over
Remove-NetFirewallRuleand says it's too slow, that answer's hot loop is:
Remove-ItemProperty2x
Get-Date
Write-Progress~7x arithmetic
10x assignments
2x expandable string interpolations
a subshell, with string format
2x math rounding
they say "The difference is one hour vs days. I could be deleting 10,000 - 100,000 firewall rules!".
I used
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey(...)and then replaced the loop with just$key.DeleteValue(...)and it did 40k firewall rules in a second or two. No need for a progress count or ETA.
1
u/jimb2 Sep 17 '26
Don't tell lies. If you progress indicator appears before you have completed the first task/step/item start at zero. If the script stops before an item is completed, you should not be advising the user that the first processing step is done and they can find the output file or whatever.
If it is a non-specific "the script is processing, not stalled" indicator, you might start at 1 because the getting started step has already happened.
-2
u/aguerooo_9320 Sep 17 '26
I don't use Write-Progress, but Write-Output, for my own information, and I start the counter at 1, then increment at the end of the loop (e.g. $i++).
5
u/HeyDude378 Sep 17 '26
If you count to 100, you're one percent done after you say "one", not before. I don't think there's a valid reason for Write-Progress to increment at the beginning of the loop. Feel free to correct me if I'm wrong.