neděle 11. listopadu 2018

Display the times computer was running using PowerShell and Python 3

One day I was curious to see when I yesterday went to bed. Because I know that it was something like twenty minutes after closing down my computer I went there and found the time of that event in the Windows' Event Viewer. That lead me to the idea of writing simple script which would display something like last ten durations I used my computer.

Trying to get things quickly as possible, I choose to combine three programming languages:

  • PowerShell to get the data, because it is really easy with it.
  • Python 3.6 to do the main work, because I know it much more than Powershell. 
  • Batch file :)
When I have time I would like to make all PowerShell solution because I would like to learn it more and this looks like ideal opportunity.

Getting the data

Note that to run unsigned PowerShell scripts you write you might need to run:

Set-ExecutionPolicy RemoteSigned

in the PowerShell opened as an administrator. See this answer on

Getting the data from Windows Event log is really easy with PowerShell:


$boots = Get-EventLog -Log System -Source Microsoft-Windows-Kernel-Boot -InstanceID 25 -Newest 10
$boots | Select -Property TimeGenerated


$shutdows = Get-EventLog -Log System -Source Microsoft-Windows-Kernel-Power -InstanceID 42 -Newest 9
$shutdows | Select -Property TimeGenerated

Running it on command line is really easy:

C:\Users\Michal>powershell boots.ps1

11.11.2018 7:24:37
10.11.2018 6:44:16
09.11.2018 19:31:38
09.11.2018 5:59:47
08.11.2018 5:07:07
07.11.2018 19:04:54
07.11.2018 5:12:58
06.11.2018 21:09:23
06.11.2018 5:05:07
05.11.2018 18:57:44

Note that I take last ten boot times but only nine shutdowns. Because I will then match boot times to shutdown times and obviously there is always on more boot time—the last time we started our computer to run the scripts.

To be honest, the InstanceIDs are taken just just by guess by looking at Event Viewer. They works OK for me, however note that I always turn this computer off, never make it sleep or hibernated so I have not tested the scripts in that situation.

Merging the data


from datetime import datetime
from subprocess import PIPE, run

def get_datetimes(type):
    datetime_strings = run(
        f'powershell {type}s.ps1', 
    datetime_objects = []
    for datetime_string in datetime_strings:
        # skip non-dates
        if ":" not in datetime_string: continue
        datetime_object = datetime.strptime(
            "%d.%m.%Y %H:%M:%S"
    return datetime_objects

boot_dts     = get_datetimes("boot")
shutdown_dts = get_datetimes("shutdown")
shutdown_dts.insert(0, "Running")

combined = zip(boot_dts, shutdown_dts)
first = True
for boot, shutdown in combined:
    print(boot, "==>", shutdown, end="")
    if first: 
        first = False
        print(f"  ({ - boot})")
        print(f"  ({shutdown - boot})")

The matching is really naive. If there would be missing event, e.g. no shutdown event because of crashed computer, the data would be matched incorrectly.

Notes on calling
  • f'...{variable}' are the new Python 3.6 formatted string literals.
  • check=True will validate that the process exited OK (i.e. with zero exit code).
  • In Python 3.7 I you can use capture_output=True instead of stdout=PIPE just for the fact that it is much more readable.
After loading the times we level out the nine shutdown times to ten boot times by adding "Running" string at the begging of the array. 

Than we use zip() function to make pairs of (boot time, shutdown time) and print the pairs together with the duration (the "shutdown - boot" expression inside formatted string literal).

We must handle differently first pair when displaying the results because there is no shutdown datetime instance but just string "Running" instead. So we use current time to show how long is computer running now since the last boot time. We could have put the current time in the array shutdown_dts instead of the "Running" string to get rid of this special handling but I like to make it explicit that this is not real shutdown.

The data from our PowerShell script are without milliseconds which is actually nice because they would be useless for this anyway. This leads to the result that the duration would be displayed automatically also without milliseconds. Good—less work for us. However the returns milliseconds. To make it look the same—i.e. truncate the milliseconds we could either do some time formatting or—which I found simpler in this case—just zero them.

Running it from desktop shortcut

I wanted to put shortcut to this script to my desktop. The problem is that Windows would run it and immediately close the window so I would not see the results. I could put call to input("Press Enter to quit") at the end of the script but I don't want to make it wait for the Enter when the script is run in the command prompt window.

So I created small batch file:


@echo off

and created shortcut to that. Just make sure that all those four files (boots.ps1, shutdowns.ps1,, runtime.bat) are in the same folder so they will find each other. Also make sure that the "Start in" folder of the shortcut properties is set to the directory with these four files.

py is the standard Python Launcher for Windows which is automatically installed with Python. If it is not found, please install standard Python 3.6 or newer from the


Files are available in GitHub repository.