【问题标题】:Detect if Windows workstation is locked in PyQt5 application检测 Windows 工作站是否锁定在 PyQt5 应用程序中
【发布时间】:2015-02-19 13:09:05
【问题描述】:

我有一个 PyQt5 应用程序,我想检查 Windows 工作站是否处于锁定状态。

一开始我尝试使用sn -p See if my workstation is locked。它在我的 Windows 7 64 位上根本不起作用。它认为工作站一直处于锁定状态。

我在 SO 问题 How to detect Windows is locked? 中注意到上述解决方案可能是一个 hack,我应该使用 WTSRegisterSessionNotification。我找到了以下 sn-p Terminal Services event monitor for Windows NT/XP/2003/...。它可以按原样使用。

我已将代码简化为以下内容:

import win32con
import win32gui
import win32ts


WM_WTSSESSION_CHANGE        = 0x2B1


class WTSMonitor():
    className = "WTSMonitor"
    wndName = "WTS Event Monitor"

    def __init__(self):
        wc = win32gui.WNDCLASS()
        wc.hInstance = hInst = win32gui.GetModuleHandle(None)
        wc.lpszClassName = self.className
        wc.lpfnWndProc = self.WndProc
        self.classAtom = win32gui.RegisterClass(wc)

        style = 0
        self.hWnd = win32gui.CreateWindow(self.classAtom, self.wndName,
            style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT,
            0, 0, hInst, None)
        win32gui.UpdateWindow(self.hWnd)
        win32ts.WTSRegisterSessionNotification(self.hWnd, win32ts.NOTIFY_FOR_ALL_SESSIONS)

    def start(self):
        win32gui.PumpMessages()

    def stop(self):
        win32gui.PostQuitMessage(0)

    def WndProc(self, hWnd, message, wParam, lParam):
        if message == WM_WTSSESSION_CHANGE:
            self.OnSession(wParam, lParam)

    def OnSession(self, event, sessionID):
        print(event)

if __name__ == '__main__':
    m = WTSMonitor()
    m.start()

现在我正在尝试将它与 PyQt5 骨架合并:

import sys
from PyQt5.QtWidgets import *

class Window(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)

        self.show()

if __name__ == '__main__':    
    app = QApplication(sys.argv)
    win = Window()
    sys.exit(app.exec_())

但是,我不知道该怎么做。我所做的每一次尝试都没有奏效,该事件似乎没有被注册。知道如何完成这项工作吗?

编辑: 这是我尝试过的合并之一。

import sys
from PyQt5.QtWidgets import *
import win32gui
import win32ts


WM_WTSSESSION_CHANGE        = 0x2B1


class WTSMonitor(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)    
        self.show()
        win32ts.WTSRegisterSessionNotification(self.winId(), win32ts.NOTIFY_FOR_ALL_SESSIONS)

    def start(self):
        win32gui.PumpMessages()

    def stop(self):
        win32gui.PostQuitMessage(0)

    def WndProc(self, hWnd, message, wParam, lParam):
        if message == WM_WTSSESSION_CHANGE:
            self.OnSession(wParam, lParam)

    def OnSession(self, event, sessionID):
        print(event)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = WTSMonitor()
    win.start()
    sys.exit(app.exec_())

【问题讨论】:

  • 您能否提供您尝试(合并时)但不起作用的示例?
  • @three_pineapples - 我添加了一个合并。其他基本相同,只是没有启动/停止。我知道这是非常幼稚的方法,但我对 winapi 还不够好。我感觉win32gui.PumpMessages() 引入了第二个事件循环,它不起作用。

标签: python windows winapi pyqt


【解决方案1】:

我已将 WndProcHookMixin.py 上发布在 wxPython wiki 上的想法改编为 PyQt。它按预期工作。

import sys

from PyQt5.QtWidgets import *
import win32api
import win32con
import win32gui
import win32ts


WM_WTSSESSION_CHANGE = 0x2B1
WTS_SESSION_LOCK = 0x7
WTS_SESSION_UNLOCK = 0x8 


# http://wiki.wxpython.org/HookingTheWndProc
# http://wiki.wxpython.org/HookingTheWndProc?action=AttachFile&do=view&target=WndProcHookMixin.py
# http://wiki.wxpython.org/HookingTheWndProc?action=AttachFile&do=view&target=WndProcHookMixinCtypes.py
class WndProcHookMixin:
    def __init__(self):
        self.msgDict = {}

    def hookWndProc(self):
        self.oldWndProc = win32gui.SetWindowLong(self.winId(), win32con.GWL_WNDPROC, self.localWndProc)

    def unhookWndProc(self):
        win32api.SetWindowLong(self.winId(), win32con.GWL_WNDPROC, self.oldWndProc)

    def addMsgHandler(self, messageNumber, handler):
        self.msgDict[messageNumber] = handler

    def localWndProc(self, hWnd, msg, wParam, lParam):
        if msg in self.msgDict:
            if self.msgDict[msg](wParam, lParam) == False:
                return

        if msg == win32con.WM_DESTROY: 
            self.unhookWndProc()

        return win32gui.CallWindowProc(self.oldWndProc, hWnd, msg, wParam, lParam)


class Window(QWidget, WndProcHookMixin):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)    
        self.show()
        win32ts.WTSRegisterSessionNotification(self.winId(), win32ts.NOTIFY_FOR_ALL_SESSIONS)
        self.addMsgHandler(WM_WTSSESSION_CHANGE, self.on_session)
        self.hookWndProc()

    def on_session(self, wParam, lParam):
        event, session_id = wParam, lParam
        if event == WTS_SESSION_LOCK:
            print("Locked")
        if event == WTS_SESSION_UNLOCK:
            print("Unlocked")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    sys.exit(app.exec_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 2023-03-08
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 2010-11-18
    相关资源
    最近更新 更多