PowerShell Write-Progress

Windows PowerShell Write-ProgressPowerShell Write-Progress Cmdlet

The purpose of this cmdlet is to provide a green bar, which confirms that a time-consuming script is indeed running.  The secret of getting Write-Progress to work is positioning the cmdlet in the loop correctly.

Windows PowerShell Write-Progress Topics



Understanding the Elements of a Write-Progress Script

Scripts with a long period of inactivity often benefit from adding a Write-Progress bar to reassure the user that the code is working as planned. 

I have chosen Get-WmiObject as my vehicle to demonstrate the syntax. But first, here is a preliminary script that focuses on Write-Progress itself.  The secret of success is that 'For' Loop.

A Basic Write-Progress Script

$Max = 7
For($i = 1; $i -le $Max; $i++)
Write-Progress -Activity "Counting `$i variable" `
-Status "`$i = $i" `
-PercentComplete ($i / $max*100)
sleep 1

Note 1: Please match the three Write-Progress parameters, -Activity, -Status and -PercentComplete to what you see in the progress bar.

Example 1: Write-Progress with WMI Objects

The purpose of this example is to filter WMI classes so the output displays only those classes containing the word 'Network', or a string of your choice.  The underlying problem is the 'If' statement takes time, and would benefit from an bar showing the progression – a job for Write-Progress.

Planning the Real-life Write-Progress script
Perhaps I had a bad day, but I really struggled to make the transition from a simple example to using Write-Progress in a meaningful script.  Here is an list of what helped me reach that 'Eureka' moment.

  • The key command in this script is Get-WmiObject -List.
  • The key concept is that Write-Progress needs to be inside a loop, PowerShell's ForEach-Object is an ideal construction to meet this need.
  • I have developed the script into a function called Show-WMI; the benefit is that you can search for classes other than 'Network' more easily.
  • As with most PowerShell functions there are sections: Param(we could add more parameters), Process{The engine of the function}, also the optional Begin and End sections.

Function Global:Show-WMI{
[string]$Class ="Network"
        ) # Just one parameter
Begin {
$OutNet =""; $w=0
      } # End of begin
Process {
$WMI = Get-WmiObject -list
$WMI | ForEach-Object -Begin {Clear-Host $OutNet = "" $i=0} `
-Process {If($_.name -Match $Class) `
{$OutNet = $OutNet +$_.name +"`n";$w++};$i++;`
Write-Progress -Activity "Selecting WMI Classes" -Status "Progress:" `
-PercentComplete ($i/$WMI.count*65)} -End {$OutNet}
           } # End of Process section
"There are $w WMI classes for $Class `n"
   } # End of short End section
}  # End of function


Note 2: To be blunt, I find Microsoft's -PercentComplete parameter is difficult to configure.  I understand the math concept, I realize that we need to divide $i (number of matches) by the total WMI.count, but I am not clear on the logic behind my fudge of *65.

Note 3: Please observe how creating a -Class param means the function adds value to the underlying command; it enables you to search for other types of WmiObject, for example: Show-WMI -Class TCPIP

Guy Recommends: Free WMI Monitor for PowerShellSolarwinds Free WMI Monitor for PowerShell

Windows Management Instrumentation (WMI) is one of the hidden treasures of Microsoft’s operating systems.  Fortunately, SolarWinds have created a Free WMI Monitor so that you can discover these gems of performance information, and thus improve your PowerShell scripts.

Take the guess work out of which WMI counters to use when scripting the operating system, Active Directory, or Exchange Server. Give this WMI monitor a try – it’s free.

Download your free copy of WMI Monitor

Example 2: Write-Progress with Two Bars

This variation of Example 1, introduces a second Write-Progress command.  My reasoning is that we need a bar to appear while Get-WmiObject builds its list.

Function Global:Show-WMI{
[string]$Class ="Network"
     ) # Just one parameter
Begin {
$OutNet =""; $w=0;
    } # End of begin
Process {
For ($a =1; $a -le 1; $a++) {
Write-Progress -Id 0 -ParentId 1 -Activity "Collecting WMI objects" `
-Status "Wait" -PercentComplete (50)
$WMI = Get-WmiObject -List
$WMI | ForEach-Object -Begin {Clear-Host $OutNet = "" $i=0} `
-Process {If($_.name -Match $Class) `
{$OutNet = $OutNet +$_.name +"`n";$w++};$i++;
Write-Progress -Id 1 -Activity "Selecting WMI Classes" -Status "Progress:" `
-PercentComplete ($i/$WMI.count*65)} -End {$OutNet}
             } # End of inner loop
         } # End of outer loop
"There are $w WMI classes for $Class `n"
     } # End of end!
} # End of function

Note 4: I interpret ParentId as: 'I am a child of Id 1'; or 'I rely on Id 1'.

See more on WMI Classes »

Further Research For More Write-Progress Parameters

# Extra Parameters for PowerShell's Write-Progress
Get-Help Write-Progress -Full

Note 5: Get-Help always reveals extra parameters, such as -CurrentOperation.  Appending -Full provides useful examples of how to use the cmdlet.

Guy Recommends:  A Free Trial of the Network Performance Monitor (NPM)Review of Orion NPM v11.5 v11.5

SolarWinds’ Network Performance Monitor will help you discover what’s happening on your network.  This utility will also guide you through troubleshooting; the dashboard will indicate whether the root cause is a broken link, faulty equipment or resource overload.

What I like best is the way NPM suggests solutions to network problems.  Its also has the ability to monitor the health of individual VMware virtual machines.  If you are interested in troubleshooting, and creating network maps, then I recommend that you try NPM now.

Download a free trial of Solarwinds’ Network Performance Monitor

Example 3: Basic PowerShell Write-Progress Script

This script does not do any useful work, it just provides a simple Write-Progress example with an inner and outer loop.

$Max = 5
For($Outer = 1; $Outer -le $Max; $Outer++)
Write-Progress -Activity "Counting Outer" `
-Status "`$Outer = $Outer" -PercentComplete ($Outer / $Max*100) -Id 1
Start-Sleep -s 1
For($Inner = 1; $Inner -le ($Max*2); $Inner++)
Write-progress -Activity "Counting Inner"  -CurrentOperation " Sleep is the only work!"`
-Status "`$Inner = $Inner" -PercentComplete ($Inner / $Max*50) -ParentId 1
Start-Sleep -m 300
    } #end for Inner
} #end for Outer

Note 6: While the outer loop uses $Max*100, the inner loop, which has twice as many iterations, needs half the value hence: $Max*50.

Note 7: The only work these example loops do is Start-Sleep!

Example 4: Write-Progress with 'Jobs'

Here is a neat script which creates Write-Progress bars in co-operation with PowerShell's 'Job' family of cmdlets.

Scenario: You have a script which takes a long time to search the registry, and you want to display a progress bar.

Solution: Employ PowerShell's Start-Job and Receive-Job cmdlets.

$Winlogon = Start-Job -ScriptBlock {
Get-ChildItem HKLM:\Software\Microsoft -recurse -Include Winlogon -EA 4
$Prog = 10
For($i = 1; $i -le $Prog; $i++)
Write-Progress -Activity "Please wait – retrieving values … " -Status " $i of $Prog " `
-PercentComplete ($i / $max*100) -id 1
Start-Sleep 3
Receive-Job -Job $Winlogon

Researching Similar PowerShell Cmdlets

# PowerShell Write Cmdlet Research
Get-Command -Verb Write


See more PowerShell Techniques »

Summary of PowerShell Write-Progress

The purpose of this cmdlet is to provide a bar, which show users that a time-consuming script is running.  The secret of getting Write-Progress to work is to position the cmdlet in the loop correctly.

If you like this page then please share it with your friends


See more Microsoft PowerShell output tutorials:

PShell Home   • Out-File   • Out-GridView   • ConvertTo-Csv   • ConvertTo-Html   • ConvertFrom-Csv

Tee-Object   • Import-CSV   • Format-Table   • PowerShell Here-String  • ConvertFrom-JSON

Export-CliXml   • Format-List   • Read-Host    • PowerShell Get-History   • -f format   • Pipe to file

Please email me if you have a better example script. Also please report any factual mistakes, grammatical errors or broken links, I will be happy to correct the fault.