Tuesday, December 18, 2018

Windows Shutdown Timer

Windows Shutdown Timer V0.23

I decided to get back to what I enjoy the most, simple Windows app’s, and they don’t come much simpler than a shutdown timer.

  1. Get time to shutdown from user
  2. Count down to zero
  3. Shutdown computer

That was my initial assessment, the reality was quite different (isn’t it always?).

python-windows shutdown timer-v023-screenshot1

Little was I to know, as I started work on the GUI, that this simple little app would need to use threading and the .after command, two things I previously had real trouble with, when writing RIG.

I doubt I would of took up the challenge had I known this at the start, but by the time it dawned on me that threading was essential to make this work I had already written most of the code.

After the confidence knock that I had received with Bletchley, I was still looking to get back on my feet with simple stuff, in order to rebuild my programming ego to the point where I could fool myself into thinking I was at least a competent programmer, some chance.

Building The GUI

Using WAC, construction of the GUI was quick and fairly straight-forward, though I had a lot of trouble aligning some widgets and text as I wanted them, so I resorted to a GUI I had already made in a previous project, HFT, and adapted that.

python-windows shutdown timer-v0.1

When I started out, I thought this was all that was going to be needed, GUI wise.  I had forgotten WST would need a label or something outputting how long to go before shutdown.

I played with the idea of using the spinboxes to make those values do the counting down, using the .get and .set commands, it seemed quite a neat, and maybe novel, idea, but I soon realised that the user could easily mess it all up by changing the values during the count-down.

Maybe on reflection it would of made WST more flexible, being able to change the timer at will, but I had the feeling this could lead to complications later on, so I decided to keep it simple with a standard label frame, with label and text.

python-windows shutdown timer-v0.6

WST Was Crap, And Then The GUI Froze

By now, my heart had sunk when the GUI froze solid during the countdown, until it reached zero.  The countdown timer would have no effect on the GUI until it was too late.  WST was crap and the GUI was likely to crash as a non-responding Windows program, way before most countdowns would end, it sucked ass.  It was all a waste of time, unless I could work out how to use threading.

How To Make A Thread

After going through tons of highly detailed docs and overblown complex explanations from and for scientist, I got lucky, (this is becoming a happy habit lately).  I found a page that laid out a simple bare-bones example of how to make a thread

import threading
def gfg():
    print("GeeksforGeeks\n")
timer = threading.Timer(2.0, gfg)
timer.start()

Once timer.start() has been run, the thread will execute the “gfg” function every two seconds (2.0).  What this essentially means is that any code you put inside the “gfg” function will run as a background task and not freeze the GUI up, awesome.  Why did I not see this example before?

Wangling The Errors

So, that problem was kind of solved.  I had many “not in main loop” errors when I tried to add the thread code to the GUI.  I must admit, I still don’t get that part, but somehow I wangled my way around the errors.

Countdown Timer Angst

I should have been almost done, bar the testing and tidying up, but as is the norm with moi, I came across what appeared to be an intractable problem for my limited brain.

I have to admit here, my dear reader, that I can’t remember properly how it all panned out, and exactly what and when happened where, it’s all a bit of a haze.  I was doing many short sessions of a couple of hours at a time, trying new things and returning back to old code, so please forgive me if I’m incorrect with some assumptions here.

The thread was working.  I could see via a print statement it was counting down perfectly, but this was not reflected in the GUI, FFS!  What was going on?  I thought threading would solve all this?

Gawd Bless Python Bloggers Govn’r

After several Googles I found out that I had to learn about an old enemy, the .after command.  I had needed to use .after in RIG, but from the explanations I had been given and pages I had read, I simply did not understand how to implement it.

I soldiered on, and eventually got lucky, yet again, finding a simple explanation, god bless non-engineering, non-scientist, Python bloggers, I say.

How To Use .after

Stupidly, I forgot to bookmark the blog where I found this, but basically, all one needs to do is this:

ROOT.after(100, update_label)

ROOT being the root frame of your GUI (the same one you would use in ROOT.mainloop).

The “100” is how often to update in milliseconds, change to your desired timing.

update_label” is the function it calls every 100 ms (obviously you would change this to your own function).

I can’t remember exactly why, but I needed to put this same line inside the function AND in the mainloop of my code.  If I take either line out, it does not work.  I think I am probably doing something wrong here, but it works.

So, I have overcome two giant hurdles that I was too scared to tackle before because I thought they were too complex for me.  This was mainly due to over the top, stupidly complex explanations.  I’m a simple soul, and my mind works in simple ways, so keep it simple people PLEASE.  A simpleton.

This Is Not Going To Happen Any Time This Month

The next problem I came across that held me up for quite a few hours was the “datetime” module.  How can that module be so stupidly complicated?

What I had hoped to do in the countdown box was to calculate the time of shutdown by adding the system time to how many hours and minutes the user had selected.

So if the user had selected 2 hours 30 mins and the system time was 3pm it was print “Shutdown at 5.30pm” and then the hours and mins would tick down.

Oh boy, that wasn’t going to happen anytime this month I can tell you.

Even just adding hours and minutes presented problems out of my league, sod it, I decided, I’m going with just minutes all the way, keep it simple.

To convert everything to minutes I just multiplied the hours by 60 and then added that number to the selected minutes, thus 2 hours 30 minutes became 150 minutes.

Then a simple countdown of 1 minute decrements, update the label, check if zero, if so, execute shutdown.

python-wst-v010

 

I’m Starting To Get Lazy Here!

I had already spent several days more than I had wanted to on this app, so I started getting lazy (this is where i should take a rest but I rarely do).

I wanted a “Stop” button for the user so s\he could cancel the timer if required, but I couldn’t find a way to cancel the thread or the .after command, but I realised if the user just quit the program they would stop of course.  So I removed the “Stop” button and stuck a message box explaining this, just before the timer starts.  Bit of a cop-out, but what the hell.

python-windows-shutdown-timer-popup

 

How To Shut down Windows

The actual code I use to shut down Windows is from my Newb Code Snippets Collection, number 12 in fact. It’s quite simple to do:

os.system(‘shutdown -s -t 0’)

It was then that it dawned on me that I should also offer restart Windows and Log Off current user.  Damn it, there goes my GUI design again.  I should of thought of this at the beginning, but I never do.

As it turned out, a simple combobox fitted in nicely, with a bit of fiddling, it didn’t take too long.

python-windows-shutdown-timer-v0-17-dropdm

After some Googling I found out the the code for restart is :

os.system(‘shutdown -r -t 1’)

And to log off is:

os.system(“shutdown -l”)

 

How To Murder Programs And Get Away With IT

On testing, these shutdowns seemed to work fine, except occasionally the shutdown process could get stuck if I had certain programs still running, mainly Firefox or Ms Word.

I Googled and found a nice simple solution to that.

  • os.system(“taskkill /f /im chrome.exe”)
  • os.system(“taskkill /f /im firefox.exe”)
  • os.system(“taskkill /f /im winword.exe”)

You can add any program you want to the list.  I had the idea of letting the user add a troublesome program to the list, but I just couldn’t face adding that feature at the time, I wanted a working program, and quick, it had been nearly a week that I had been messing about with what should of been a four hour project 🙂  It is a decent idea though, that I will probably add sooner or later.

Now all I had to do was tidy up the GUI the best I could.  It’s definitely not the most handsome GUI I have made, but it is functional and easy to use, isn’t that the exact idea behind any GUI?  If not, then it should be.

After some successful testing I felt WST needed more than just the minutes ticking away, the GUI would look a bit dead, except once a minute a digit decrementing.  I did not feel like getting into doing seconds (as in 1\60th of a minute) at this juncture.  I may as well leave something to do for a future update eh!.

Just Showing Off

The idea that I eventually came up with was a (very) simple animation of the “<” and “>” interchanging, just so that the user knows the program is alive and well, plus it shows off my .after skills LOL.

python-windows shutdown timer-v023-screenshot

Well, after all that cobblers, I can’t create a stand alone .exe with Pyinstaller, it wont run at all, and gives no errors.  I will return when I have experimented more.  It works fine from the source code, so you can use it if you wish.

Freeware Python Source Code

You can get the source code to Windows Shutdown Timer V0.23 from my Dropbox as always.

 

Using Python V3.6.5(32 bit) on Windows 7, (64 bit).

Previous post:  The Insult Machine Update V1.36

Advertisements


from Python Coder
via read more

No comments:

Post a Comment

TestDriven.io: Working with Static and Media Files in Django

This article looks at how to work with static and media files in a Django project, locally and in production. from Planet Python via read...