本文介绍了Python - Windows 关闭事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 win32api.setConsoleCtrlHandler() 时,我可以从 Windows 接收关闭/注销/等事件,并彻底关闭我的应用程序.

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

然而,这只适用于在 python.exe 下运行应用程序(即它有一个控制台窗口),而不是在 pythonw.exe 下(没有控制台窗口).

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

当您没有控制台和窗口来接收这些事件时,Windows 中是否有一种等效的方式来接收这些事件?或者,是否有隐藏控制台窗口的编程方式?

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?

要明确 - 我的目标是能够成功接收 Windows 关机/注销/等事件,而不会显示任何类型的控制台窗口.

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.

我一直在玩,而且我已经走得更远了.我为此写了一段测试代码.当我执行taskkill/im pythonw.exe"时 - 它会收到消息.

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.

但是,当我在 Windows 上关闭、重新启动或注销时,我没有收到任何消息.

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

这里是整件事:

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

推荐答案

这里的问题是 HWND_MESSAGE 窗口类型实际上并不接收广播消息——如 WM_QUERYENDSESSION 和 WM_ENDSESSION.

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

因此,我没有为 CreateWindowEx() 的父窗口"参数指定 win32con.HWND_MESSAGE,而是指定了0".

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.

这篇关于Python - Windows 关闭事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 13:00