<h1>Estimated Completion Time in PowerShell</h1>

Progress Bars are all about giving the user feedback as to what the program is doing, and Powershell implements it with the Write-Progress cmdlet. It is also possible to predict the completion time by using a little math.

Possible uses for the progress bar include:

  1. Showing status of reading a large file
  2. Showing status of exploding a directory structure
  3. Showing progress of creating files or videos
  4. Showing status of processing a large number of database records
  5. Showing status of file upload or download

In my opinion, a status bar should not just show the progress, but also tell the user the estimated completion time (sometimes called ETA – Estimated Time of Arrival). This is done by computing a ratio of the word done to the work to be performed, and using that ratio along with elapsed time and TimeSpans to come up with the estimated completion time.

cls
$maxI = 250 
$startTime = get-date 
Write-Host "StartTime=$startTime"
for ($i = 1; $i -le $maxI; $i++ )
{
  write-host "`$i=$i"
  start-sleep -milliseconds 250  
  $elapsedTime = $(get-date) - $startTime 

  #do the ratios and "the math" to compute the Estimated Time Of Completion 
  $estimatedTotalSeconds = $maxI / $i * $elapsedTime.TotalSeconds 
  $estimatedTotalSecondsTS = New-TimeSpan -seconds $estimatedTotalSeconds
  $estimatedCompletionTime = $startTime + $estimatedTotalSecondsTS
  Write-Host "elapsedTime=$($elapsedTime.TotalSeconds) estimatedTotalSeconds=$estimatedTotalSeconds"
  Write-Host "estimatedCompletionTime=$estimatedCompletionTime"

  #I like to keep the width of the Write-Progress minimalized by creating three variables 
  #and substituting them into the Write-Progress statement. 
  $activityMsg = "Search in Progress"
  $percentComplete = $i / $maxI * 100 
  $statusMsg = "$percentComplete% Complete: $i out of $maxI Estimated Completion at $estimatedCompletionTime"

  write-progress -activity $activityMsg -status $statusMsg  -percentcomplete $percentComplete;
  Write-host "percent complete=$percentComplete "
}
$endTime = get-date 
$elapsedTime = $endTime - $startTime 
write-host "The End $startTime=$startTime endTime=$endTime elapseSeconds=$($elapsedTime.TotalSeconds)"

write-host "The End" 

Running in ISE, the progress bar looks like this (it actually seems to hide the first few lines in the output pane).

Powershell_Write_Progress_Bar

The command line version is not quite as pretty, but still effective:

Powershell_Write_Progress_Bar_CommandLine
WindowsClockI suggest you take this example, change the value of $maxI and/or change the sleep time, and see if you get an accurate prediction of the completion time.

Filed under: Powershell