You need to know the number of items in the pipeline to track progress.
Powershell 3.0 can give you an account of what's under development, without having to do any work outside of access to the .Count $Input property if the pipeline parameter is correctly declared. It also means that you can end the begin {} process {} end {} blocks and just have a direct function if you want.
Earlier versions do not have the Count property, so you first need to iterate and grab the pipeline to get the count, and then process it again, which is not as efficient as I will show later.
Powershell V2 Version:
function Show-ProgressV2{ param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] [PSObject[]]$InputObject, [string]$Activity = "Processing items" ) Begin {$PipeArray = @()} Process {$PipeArray+=$InputObject} End { [int]$TotItems = ($PipeArray).Count [int]$Count = 0 $PipeArray|foreach { $_ $Count++ [int]$percentComplete = [int](($Count/$TotItems* 100)) Write-Progress -Activity "$Activity" -PercentComplete "$percentComplete" -Status ("Working - " + $percentComplete + "%") } } }
Powershell V3 Version:
function Show-ProgressV3{ [CmdletBinding()] param ( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] [PSObject[]]$InputObject, [string]$Activity = "Processing items" ) [int]$TotItems = $Input.Count [int]$Count = 0 $Input|foreach { $_ $Count++ [int]$percentComplete = ($Count/$TotItems* 100) Write-Progress -Activity $Activity -PercentComplete $percentComplete -Status ("Working - " + $percentComplete + "%") } }
Efficiency
Comparing two V3 functions is about 5-6 times faster, depending on the size of the conveyor.
Consider the following pre-filtered list of files, looking for all .jpg files on my home drive, selecting the first 200 files, sort and print using the function 3 times in the pipe, for your comment:
$V2 = Measure-Command {Get-ChildItem -Filter *.jpg -Recurse ` | Show-ProgressV2 -Activity "Selecting" ` | Select-Object -First 200 ` | Show-ProgressV2 -Activity "Sorting" ` | Sort-Object -Property FullName ` | Show-ProgressV2 -Activity "Listing" ` | FL} $V3 = Measure-Command {Get-ChildItem -filter *.jpg -Recurse ` | Show-ProgressV3 -Activity "Selecting" ` | Select-Object -First 200 ` | Show-ProgressV3 -Activity "Sorting" ` | Sort-Object -Property FullName ` | Show-ProgressV3 -Activity "Listing" ` | FL} $V2 $V3
Which gives me the following timings:
PS C:\Users\Graham> C:\Users\Graham\Documents\Stack_ShowProgress_Pipeline.ps1 Days : 0 Hours : 0 Minutes : 0 Seconds : 48 Milliseconds : 360 Ticks : 483607111 TotalDays : 0.000559730452546296 TotalHours : 0.0134335308611111 TotalMinutes : 0.806011851666667 TotalSeconds : 48.3607111 TotalMilliseconds : 48360.7111 Days : 0 Hours : 0 Minutes : 0 Seconds : 8 Milliseconds : 335 Ticks : 83358374 TotalDays : 9.6479599537037E-05 TotalHours : 0.00231551038888889 TotalMinutes : 0.138930623333333 TotalSeconds : 8.3358374 TotalMilliseconds : 8335.8374