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 superuser.com.

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

boots.ps1

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

shutdowns.ps1

$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

TimeGenerated
-------------
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

runtime.py

#!python3

from datetime import datetime
from subprocess import PIPE, run

def get_datetimes(type):
    datetime_strings = run(
        f'powershell {type}s.ps1', 
        check=True, 
        stdout=PIPE, 
        encoding="ASCII"
    ).stdout.split("\n")
    
    datetime_objects = []
    for datetime_string in datetime_strings:
        # skip non-dates
        if ":" not in datetime_string: continue
        datetime_object = datetime.strptime(
            datetime_string.strip(), 
            "%d.%m.%Y %H:%M:%S"
        )
        datetime_objects.append(datetime_object)
    
    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"  ({datetime.now().replace(microsecond=0) - boot})")
    else:
        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 subprocess.run():
  • 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 datetime.now() 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:

runtime.bat

@echo off
py runtime.py
pause

and created shortcut to that. Just make sure that all those four files (boots.ps1, shutdowns.ps1, runtime.py, 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 python.org.


Files

Files are available in GitHub repository.

neděle 15. dubna 2018

Tutor: Programování s Pythonem

Tutor: Programování s Pythonem

Zkusil jsem udělat takový tutoriál pro začátečníky. 

Tenhle tutoriál je určen pro ty, kteří by se chtěli naučit programovat. A to v jazyce zvaném Python. Ale více se soustředím na programování obecně, než na samotný Python. Protože mám pocit, že je spousta tutoriálů, které se soustředí na programovací jazyk, ale mnohem míň těch, které se soustředí na základy nějakého toho programátorského myšlení :)

pátek 30. března 2018

Porovnání Ruby a Pythonu 3

Sepsal jsem porovnání některých prvků Ruby a Pythonu 3:
http://mol1111.users.sourceforge.net/rb-py.html
Může se to hodit všem, co jeden z těhle jazyků znají a chtějí se naučit ten druhý (nebo někoho takového vy učíte). Ale myslím si, že ten text může být i zajímavý pro ty, kteří jsou začátečníci-mírně pokročilí v jednom z nich, protože v některých věcech jde relativně do hloubky. A nebo naopak pro ty, které jednoduše zajímá, jak se věci dělají jinde.
Vzniklo to jako neplánovaný výsledek mojí diplomky, což byl překladač Ruby do Pythonu 3.
Uvítám jakékoli připomínky a bugreporty (jo, v IE 11 se to nezobrazuje správně, to je ale wontfix :) ).
Enjoy :)

pátek 2. března 2018

Total Commander na maximum I

Total Commander na maximum I

Tentokrát tutoriál pro oblíbený souborový manažer :)

Textová verze

Nic moc video verze

Rychlé hledání
Oblíbené složky
Záložky
Vynechávané soubory
Klávesová zkratka pro přepínání skrytých souborů

sobota 17. února 2018

Jak přežít Word a nezbláznit se z toho

Kamarádka mě inspirovala k vytvoření videa s pár tipy pro ty, kteří používají Word a mají pocit, že jim Word hází klacky pod nohy 
Můj první tutoriál, tak prosím o trochu shovívavosti k mnoha nedostatkům 

Video verze

Textová verze

Pokračování – čísla stránek a oddíly