Search code examples
powershellstopwatch

How much time did I spend at powershell?


Powershell using the $profile file, I want to find out how much time I spend on powershell every time it happens, print it to a file.

for example

24.11.2018, 13:41 -  1 hour 23 minute 12 second
11.11.2018, 13:41 -  2 hour 3 minute 2 second
11.11.2018, 13:41 -  1 hour 43 minute 42 second
...
...

The contents of a file named ps_time_history.txt are shown above. I turned on the powershell screen 3 times and it shows how long it is on.

I've written a script as below, but I can't get the solution as I want.

I wrote a script into the $profile file as below, but I can't get the solution the way I want it.

Start-Job  -scriptblock 
{ 
  $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
  $StopWatch.Start();

  $date=((Get-Process -Name powershell | Sort-Object StartTime | where { $_ }).StartTime | Select -Last 1);
  $id=((Get-Process -Name powershell | Sort-Object StartTime | where { $_  }).id | select -Last 1 );


  while ($StopWatch.IsRunning)
   {
      Start-Sleep -Seconds 1
      if((Get-Process -id $id -ErrorAction SilentlyContinue))
      {
        $time=[string]$StopWatch.Elapsed.Hours+":"+[string]$StopWatch.Elapsed.Minutes+":"+[string]$StopWatch.Elapsed.Seconds;
        echo  ([string]$date+" - "+$time) >> ~\Desktop\ps_time_history.txt;
      }
      else
      {  
       $StopWatch.Stop();
      }
   }
 }

I got the date and id number of the recently opened powershell app. The timer is running as long as the powershell screen is on. The timer needs to stop when the powershell screen is turned off.

The script I'm writing is doing the ps_time_history.txt file every second. But I don't want that. Let Powershell write down how much time I spent when I closed it.

11/29/2018 02:23:17 - 0: 0: 1
11/29/2018 02:23:17 - 0: 0: 2
11/29/2018 02:23:17 - 0: 0: 3
11/29/2018 02:23:17 - 0: 0: 4
11/29/2018 02:23:17 - 0: 0: 5
11/29/2018 02:23:17 - 0: 0: 6
11/29/2018 02:23:17 - 0: 0: 7
11/29/2018 02:23:17 - 0: 0: 8
11/29/2018 02:23:17 - 0: 0: 9
11/29/2018 02:23:17 - 0: 0: 10
11/29/2018 02:23:17 - 0: 0: 11
11/29/2018 02:23:17 - 0: 0: 12
11/29/2018 02:23:17 - 0: 0: 13

This problem seems a little complicated. How can I solve this problem or is there a shorter way?


Solution

  • Considering that you want to log session duration with second-accuracy, instead of messing with a Stopwatch I think it'd be sufficient to simply store the session start time and calculate the duration from there...

    $sessionStartTime = Get-Date;
    

    There's a negligible difference, but if you wanted to start "counting" not from when the session becomes "available" but when the process starts, you could use the $PID automatic variable to get the PowerShell process instance and save its StartTime property...

    $sessionStartTime = Get-Process -Id $PID | Select-Object -ExpandProperty 'StartTime';
    

    This complete $PROFILE script works for me using the Exiting engine event to run a ScriptBlock when the session is ending:

    [DateTime] $sessionStartTime = Get-Date;
    
    Register-EngineEvent `
        -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) `
        -SupportEvent `
        -Action {
            [DateTime] $sessionExitTime = Get-Date;
            [TimeSpan] $sessionDuration = $sessionExitTime - $sessionStartTime;
            [String] $logLine = "$sessionExitTime - $sessionDuration";
    
            $logLine >> '~\Desktop\ps_time_history.txt';
        };
    

    Note that this only handles the case of typing exit at the console. The logging code is not run when clicking the Close ("X") button on the PowerShell console window.

    Using the default formatting for DateTime and TimeSpan this outputs:

    11/28/2018 18:26:48 - 00:00:03.1026319
    

    If you don't want the duration to include fractional seconds you can use custom TimeSpan formatting like this...

    [String] $logLine = '{0:d} {0:HH\:mm\:ss} - {1:HH\:mm\:ss}' -f $sessionExitTime, $sessionDuration;