17

When using win32api.setConsoleCtrlHandler(), I'm able to receive shutdown/logoff/etc events from Windows, and cleanly shut down my app.

However, this only works when running the app under python.exe (i.e., it has a console window), but not under pythonw.exe (no console window).

Is there an equivalent way in Windows to receive these events when you have no console and no window to receive them? Or, is there a programmatic way to hide the console window?

To be clear - my goal is to be able to successfully receive Windows shutdown/logoff/etc events, without having any kind of console window showing.

EDIT: I've been playing around, and I've gotten quite a bit further. I wrote a piece of test code for this. When I do a taskkill /im pythonw.exe - it will receive the message.

However, when I do a shutdown, restart, or logoff on Windows, I do not get any messages.

Here's the whole thing:

""" Testing Windows shutdown events """

import win32con
import win32api
import win32gui
import sys
import time

def log_info(msg):
    """ Prints """
    print msg
    f = open("c:\\test.log", "a")
    f.write(msg + "\n")
    f.close()

def wndproc(hwnd, msg, wparam, lparam):
    log_info("wndproc: %s" % msg)

if __name__ == "__main__":
    log_info("*** STARTING ***")
    hinst = win32api.GetModuleHandle(None)
    wndclass = win32gui.WNDCLASS()
    wndclass.hInstance = hinst
    wndclass.lpszClassName = "testWindowClass"
    messageMap = { win32con.WM_QUERYENDSESSION : wndproc,
                   win32con.WM_ENDSESSION : wndproc,
                   win32con.WM_QUIT : wndproc,
                   win32con.WM_DESTROY : wndproc,
                   win32con.WM_CLOSE : wndproc }
    
    wndclass.lpfnWndProc = messageMap
    
    try:
        myWindowClass = win32gui.RegisterClass(wndclass)
        hwnd = win32gui.CreateWindowEx(win32con.WS_EX_LEFT,
                                     myWindowClass, 
                                     "testMsgWindow", 
                                     0, 
                                     0, 
                                     0, 
                                     win32con.CW_USEDEFAULT, 
                                     win32con.CW_USEDEFAULT, 
                                     win32con.HWND_MESSAGE, 
                                     0, 
                                     hinst, 
                                     None)
    except Exception, e:
        log_info("Exception: %s" % str(e))
    

    if hwnd is None:
        log_info("hwnd is none!")
    else:
        log_info("hwnd: %s" % hwnd)
    
    while True:
        win32gui.PumpWaitingMessages()
        time.sleep(1)

I feel like I'm pretty close here, but I'm definitely missing something!

2 Answers 2

16

The problem here was that the HWND_MESSAGE window type doesn't actually receive broadcast messages - like the WM_QUERYENDSESSION and WM_ENDSESSION.

So instead of specifying win32con.HWND_MESSAGE for the "parent window" parameter of CreateWindowEx(), I just specified 0.

Basically, this creates an actual window, but I never show it, so it's effectively the same thing. Now, I can successfully receive those broadcast messages and shut down the app properly.

3
  • how to execute this... i tried the run the scriipt provided, but it doesnot return ant system Logogg,shutdown events or even if i kill the task from task manager
    – Rao
    Commented Dec 13, 2012 at 19:52
  • On Windows 10, this only works with python.exe, not pythonw.exe.
    – Karalga
    Commented Oct 25, 2020 at 9:28
  • This is not working for me. I have python 3.10. Commented Dec 12, 2021 at 1:37
5

If you don't have a console, setting a console handler of course can't work. You can receive system events on a GUI (non-console) program by making another window (doesn't have to be visible), making sure you have a normal "message pump" on it serving, and handling WM_QUERYENDSESSION -- that's the message telling your window about shutdown and logoff events (and your window can try to push back against the end-session by returning 0 for this message). ("Windows Services" are different from normal apps -- if that's what you're writing, see an example here).

1
  • I tried the above code but i never get the system event firing at logoff/shutdown. Can you help me out here....?
    – Rao
    Commented Dec 17, 2012 at 10:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.