当使用win32api.setConsoleCtrlHandler(),我能够从Windows接收关机/注销/等事件,并干净地closures我的应用程序。
但是,这只适用于在python.exe下运行应用程序(即它有一个控制台窗口),但不能在pythonw.exe(无控制台窗口)下运行。
当没有控制台,也没有窗口可以接收这些事件时,Windows中是否有等价的方法来接收这些事件? 或者,有没有一种编程方式来隐藏控制台窗口?
要清楚 – 我的目标是能够成功地接收Windows关机/注销/等事件,而无需任何forms的控制台窗口显示。
编辑:我一直在玩,我已经进一步了。 我为此写了一段testing代码。 当我做一个“taskkill / im pythonw.exe” – 它会收到消息。
但是,当我在Windows上执行关机,重新启动或注销时,我没有收到任何消息。
这是整个事情:
""" Testing Windows shutdown events """ import win32con import win32api import win32gui import sys import time #import os 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)
我觉得我在这里很亲密,但我肯定错过了一些东西!
这里的问题是,HWND_MESSAGE窗口类型实际上并不接收广播消息,如WM_QUERYENDSESSION和WM_ENDSESSION。
因此,我没有为CreateWindowEx()的“父窗口”参数指定win32con.HWND_MESSAGE,而只是指定了“0”。
基本上,这创建了一个实际的窗口,但我从来没有表现出来,所以它是相同的事情。 现在,我可以成功接收这些广播消息,并正确关闭应用程序。
如果你没有一个控制台,设置一个控制台处理程序当然是行不通的。 您可以在GUI(非控制台)程序上接收系统事件,方法是创建另一个窗口(不必是可见的),确保您有一个正常的“消息泵”服务,并处理WM_QUERYENDSESSION
– 这是消息告诉你的窗口关于关闭和注销事件(你的窗口可以尝试通过返回0消息来推回结束会话)。 (“Windows服务”与普通应用程序不同 – 如果您正在编写这些应用程序,请参阅此处的示例)。