Pffffieeuw… This was quite the puzzle! Finally got an easy progress bar when I need to execute those long-running batch commands.
Just use this function in your pipeline. It works the same as a Foreach-Object loop. Only it displays a progress bar 🙂
Example:
1..200 | Show-Progress { $_ }

How does it work?
Show-Progress is just a fancy way of using Write-Progress. It accepts 2 parameters: $Input and $ScriptBlock.
$Input
This parameter accepts your current object in the pipeline. It then adds a new property ItemNumber. $ItemNumber is used to calculate how much items are piped through. $PipelineBuffer then stores the entire object so that we can use this “new” object in our next pipe.
$ScriptBlock
Next, the scriptblock takes over. The $ScriptBlock parameter tries to be what it says it would be. That is, a scriptblock.
Since we essentially copied over the piped object to our $PipelineBuffer, we can easily use this object as if it were the original. Only addition is the $Itemnumber. So, we simply use this object to perform our scriptblock on.
Write-Progress
Now, we can calculate our $PercentageComplete. Since we used $a as a temporary counter and since we didn’t update it since our last object, this reflects the total amount of items in our original object.
$a = Total amount of items in original object
$ItemNumber = Number of the current item in the pipeline
$PercentageComplete = 100 / $a * ($_.ItemNumber + 1)
And here is the code:
function Show-Progress {  param ( [Parameter( Mandatory=$True, ValueFromPipeline=$True )] $Input,  [parameter( Position=0, Mandatory=$True )] $ScriptBlock )  $PipelineBuffer = $Input | ForEach-Object -Begin {$a = 0} { Add-Member -NotePropertyName ItemNumber -NotePropertyValue $a -InputObject $_ -PassThru $a ++ }  $PipelineBuffer | ForEach-Object { $PercentageComplete = 100 / $a * ($_.ItemNumber + 1) Write-Progress -PercentComplete $PercentageComplete -Activity "Executing command" -Status "$PercentageComplete% complete" Invoke-Command $ScriptBlock } }