36

I have a script that kicks off an event and waits for the user to press any key to stop the script execution. I was trying to find a way to show a timer (how long the script has been running) while waiting for user input at Read-Host. Is there a way to accomplish this?


This works

$Time = [System.Diagnostics.Stopwatch]::StartNew()
while ($true) {
    $CurrentTime = $Time.Elapsed
    write-host $([string]::Format("`rTime: {0:d2}:{1:d2}:{2:d2}",
                                  $CurrentTime.hours,
                                  $CurrentTime.minutes,
                                  $CurrentTime.seconds)) -nonewline
    sleep 1
    if ($Host.UI.RawUI.KeyAvailable -and ("q" -eq $Host.UI.RawUI.ReadKey("IncludeKeyUp,NoEcho").Character)) {
        Write-Host "Exiting now"
        break;
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jeff
  • 905
  • 2
  • 8
  • 17
  • Take a look here for using WPF UI in backgound in powershell http://www.nivot.org/blog/post/2008/05/23/BackgroundTimerPowerShellWPFWidget – CB. Oct 10 '13 at 07:13

5 Answers5

38

This gave me the output I was after :)

$StartTime = $(get-date)

$elapsedTime = $(get-date) - $StartTime

$totalTime = "{0:HH:mm:ss}" -f ([datetime]$elapsedTime.Ticks)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
m0del101
  • 381
  • 3
  • 2
19

From the article Measuring Elapsed Time in Powershell (archived copy):

Assuming that the variable $script:StartTime was set at the beginning of your script, elapsed time can be determined using either of the following methods:

$elapsedTime = new-timespan $script:StartTime $(get-date)

or

$elapsedTime = $(get-date) - $script:StartTime

Both methods work exactly the same and produce a System.TimeSpan object.

So, using the above example, you could set $script:StartTime before Read-Host and then call $elapsedTime = $(get-date) - $script:StartTime after.

superjos
  • 12,189
  • 6
  • 89
  • 134
xelco52
  • 5,257
  • 4
  • 40
  • 56
7

Using a timer class (RIP poshtips) gave me something like this:

$Time = [System.Diagnostics.Stopwatch]::StartNew()
while ($NoEvent) {
    $CurrentTime = $Time.Elapsed
    write-host $([string]::Format("`rTime: {0:d2}:{1:d2}:{2:d2}",
                                  $CurrentTime.hours,
                                  $CurrentTime.minutes,
                                  $CurrentTime.seconds)) -nonewline
    sleep 1

    #Handle event
    if(event){$NoEvent = false}
}

Where $NoEvent is your event/boolean (key press func, etc.).

Sweet_Pete
  • 403
  • 4
  • 10
4

I'm happy with this little function expanded on from Xelco52's answer

$startTime = $(get-date)
write-host "Elapsed:00:00:00"
$NoEvent = $true
While ($NoEvent)
{
  Start-Sleep 1
  $elapsedTime = new-timespan $startTime $(get-date)
  write-host "Elapsed:$($elapsedTime.ToString("hh\:mm\:ss"))"  

  #Handle event
  if(event){$NoEvent = $false} 
}
Clinton Ward
  • 2,441
  • 1
  • 22
  • 26
3

TLDR answer

$StartTime = $(get-date)
#...do something...
$elapsedTime = $(get-date) - $StartTime

Most of the times $elapsedTime.TotalSeconds or $elapsedTime.TotalMilliseconds is what you want.

ndemou
  • 4,691
  • 2
  • 30
  • 33