Python – Eventos de cierre de Windows

Al usar win32api.setConsoleCtrlHandler (), puedo recibir eventos de apagado / cierre de sesión / etc. de Windows y cerrar mi aplicación limpiamente.

Sin embargo, esto solo funciona cuando se ejecuta la aplicación en python.exe (es decir, tiene una ventana de consola), pero no en pythonw.exe (sin ventana de consola).

¿Existe una forma equivalente en Windows para recibir estos eventos cuando no tiene una consola y ninguna ventana para recibirlos? O, ¿hay una manera programática de ocultar la ventana de la consola?

Para ser claros, mi objective es poder recibir con éxito los eventos de apagado / cierre de sesión / etc. de Windows, sin que se muestre ningún tipo de ventana de consola.

EDITAR: He estado jugando, y he ido un poco más lejos. Escribí una pieza de código de prueba para esto. Cuando hago un “taskkill / im pythonw.exe” – recibirá el mensaje.

Sin embargo, cuando hago un cierre, reinicio o cierre de sesión en Windows, no recibo ningún mensaje.

Aquí está todo el asunto:

""" 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) 

Siento que estoy muy cerca de aquí, ¡pero definitivamente me estoy perdiendo algo!

El problema aquí fue que el tipo de ventana HWND_MESSAGE no recibe realmente mensajes de difusión, como WM_QUERYENDSESSION y WM_ENDSESSION.

Así que, en lugar de especificar win32con.HWND_MESSAGE para el parámetro “ventana principal” de CreateWindowEx (), acabo de especificar “0”.

Básicamente, esto crea una ventana real, pero nunca la muestro, así que efectivamente es lo mismo. Ahora, puedo recibir con éxito esos mensajes de difusión y cerrar la aplicación correctamente.

Si no tiene una consola, configurar un controlador de consola, por supuesto, no puede funcionar. Puede recibir eventos del sistema en un progtwig GUI (no de consola) haciendo otra ventana (no tiene que ser visible), asegurándose de que tenga una “bomba de mensajes” normal en su servicio y manejando WM_QUERYENDSESSION – ese es el mensaje informar a su ventana sobre los eventos de apagado y cierre de sesión (y su ventana puede intentar hacer retroceso contra la sesión final devolviendo 0 para este mensaje). (Los “servicios de Windows” son diferentes de las aplicaciones normales: si eso es lo que está escribiendo, vea un ejemplo aquí ).