简体   繁体   English

在 Python 3 中,如何判断 Windows 是否被锁定?

[英]In Python 3, how can I tell if Windows is locked?

How can I check whether a Windows OS workstation is locked?如何检查 Windows 操作系统工作站是否被锁定? (eg Win+L or choosing the lock option after Ctrl+Alt+Del.) (例如 Win+L 或在 Ctrl+Alt+Del 之后选择锁定选项。)

I want something like ctypes.windll.user32.isWorkstationLocked() .我想要像ctypes.windll.user32.isWorkstationLocked()这样的东西。

This code worked today for me on four different Windows 7 and 10 machines, try something similar:这段代码今天在四台不同的 Windows 7 和 10 机器上对我有用,尝试类似的东西:

import ctypes
import time
user32 = ctypes.windll.User32
time.sleep(5)
#
#print(user32.GetForegroundWindow())
#
if (user32.GetForegroundWindow() % 10 == 0): print('Locked')
# 10553666 - return code for unlocked workstation1
# 0 - return code for locked workstation1
#
# 132782 - return code for unlocked workstation2
# 67370 -  return code for locked workstation2
#
# 3216806 - return code for unlocked workstation3
# 1901390 - return code for locked workstation3
#
# 197944 - return code for unlocked workstation4
# 0 -  return code for locked workstation4
#
else: print('Unlocked')

Edit: Also, this one works today:编辑:另外,这个今天有效:

import subprocess
import time
time.sleep(5)
process_name='LogonUI.exe'
callall='TASKLIST'
outputall=subprocess.check_output(callall)
outputstringall=str(outputall)
if process_name in outputstringall:
    print("Locked.")
else: 
    print("Unlocked.")

You can get the window on top, when the session is locked, the function return 0.您可以在顶部获取窗口,当会话被锁定时,该函数返回 0。

import ctypes
user32 = ctypes.windll.User32

def isLocked():
    return user32.GetForegroundWindow() == 0

A hacky I discovered to get around to see if Windows 10 is locked is to look at the running processes using psutil.我发现要查看 Windows 10 是否被锁定的一个技巧是使用 psutil 查看正在运行的进程。 You then search to see if LogonUI.exe is running.然后搜索以查看 LogonUI.exe 是否正在运行。 This process only runs if there when a user has a locked session.此过程仅在用户锁定会话时运行。

Note: If you use switch users this process will show as running and this workaround will not work.注意:如果您使用切换用户,此过程将显示为正在运行,并且此解决方法将不起作用。 Windows actually spawns multiple LogonUI.exe processes, one per logged on locked user. Windows 实际上会生成多个 LogonUI.exe 进程,每个登录的锁定用户一个。 It is only useful where only one person is logged on at a time.它仅在一次只有一个人登录的情况下有用。

import psutil

for proc in psutil.process_iter():
    if(proc.name() == "LogonUI.exe"):
        print ("Locked")

Something like this should do the trick:像这样的事情应该可以解决问题:

import time
import ctypes

user32 = ctypes.windll.User32
OpenDesktop = user32.OpenDesktopA
SwitchDesktop = user32.SwitchDesktop
DESKTOP_SWITCHDESKTOP = 0x0100

while 1:
  hDesktop = OpenDesktop ("default", 0, False, DESKTOP_SWITCHDESKTOP)
  result = SwitchDesktop (hDesktop)
  if result:
    print "Unlocked"
    time.sleep (1.0)
  else:
    print time.asctime (), "still locked"
    time.sleep (2)

What works for me on Windows 10 Pro is getting the foreground window:在 Windows 10 Pro 上对我有用的是获取前景窗口:

whnd = win32gui.GetForegroundWindow()
(_, pid) = win32process.GetWindowThreadProcessId(whnd)
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
filename = win32process.GetModuleFileNameEx(handle, 0)
window_text = win32gui.GetWindowText(whnd)

This returns Windows Default Lock Screen as window title and C:\\Windows\\SystemApp\\Microsoft.LockApp_<randomcharacters>\\LockApp.exe as filename when locked.这将返回Windows Default Lock Screen作为窗口标题和C:\\Windows\\SystemApp\\Microsoft.LockApp_<randomcharacters>\\LockApp.exe作为锁定时的文件名。

However, as James Koss mentioned, GetForeGroundWindow will return 0 if the user is typing their password.但是,正如 James Koss 所提到的,如果用户输入密码,GetForeGroundWindow 将返回 0。 There are also other (non-locked) situations where the current ForegroundWindow is 0, so this cannot be relied upon.还有其他(非锁定)情况,当前 ForegroundWindow 为 0,因此不能依赖。

Hi Check these 4 lines..嗨检查这4行..

returns the application name which is on the screen.. if window is locked returns the string - Windows Default Lock Screen.返回屏幕上的应用程序名称。如果窗口被锁定,则返回字符串 - Windows 默认锁定屏幕。

from win32gui import GetWindowText, GetForegroundWindow
import time
time.sleep(5)
# lock the system or open the application for a check
print(GetWindowText(GetForegroundWindow()))

From the LockWorkStation() documentation :LockWorkStation()文档

There is no function you can call to determine whether the workstation is locked.没有可以调用的函数来确定工作站是否被锁定。

Not a Python limitation, but the system itself.不是 Python 限制,而是系统本身。

Based on @Stardidi answer, this worked for me (Windows 10 Pro):基于@Stardidi 的回答,这对我有用(Windows 10 专业版):

import time
import win32gui
import win32api
import win32con
import win32process

while True:
    time.sleep(1)
    _, pid = win32process.GetWindowThreadProcessId(win32gui.GetForegroundWindow())

    try:
        handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
        filename = win32process.GetModuleFileNameEx(handle, 0)
    except Exception as _e:
        filename = "LockApp.exe"
        del _e

    current_status = "locked" if "LockApp" in filename else "unlocked"

There is no easy answer here, but you can do this via Session Tracking.这里没有简单的答案,但您可以通过 Session 跟踪来做到这一点。

From the LockWorkStation() documentation :LockWorkStation() 文档

There is no function you can call to determine whether the workstation is locked.没有function可以打电话判断工作站是否被锁。 To receive notification when the user logs in, use the WTSRegisterSessionNotification function to receive WM_WTSSESSION_CHANGE messages.要在用户登录时接收通知,请使用WTSRegisterSessionNotification function 来接收WM_WTSSESSION_CHANGE消息。 You can use session notifications to track the desktop state so you know whether it is possible to interact with the user.您可以使用 session 通知来跟踪桌面 state 以便您知道是否可以与用户交互。

Begin by registering session notifications to a window of your program.首先将 session 通知注册到程序的 window。

def register(handle: HWND) -> bool:
    """
    @param handle: handle for your message window.
    When registered, Windows Messages related to session event changes will be
    sent to the message window.
    @returns: True is session tracking is successfully registered.

    Blocks until Windows accepts session tracking registration.

    Every call to this function must be paired with a call to unregister.

    https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsregistersessionnotification
    """
    # OpenEvent handle must be closed with CloseHandle.
    eventObjectHandle: HANDLE = ctypes.windll.kernel32.OpenEventW(
        # Blocks until WTS session tracking can be registered.
        # Windows needs time for the WTS session tracking service to initialize.
        # must ensure that the WTS session tracking service is ready before trying to register
        SYNCHRONIZE,  # DWORD dwDesiredAccess
        False,  # BOOL bInheritHandle - sub-processes do not need to inherit this handle
        # According to the docs, when the Global\TermSrvReadyEvent global event is set,
        # all dependent services have started and WTSRegisterSessionNotification can be successfully called.
        # https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsregistersessionnotification#remarks
        "Global\\TermSrvReadyEvent"  # LPCWSTR lpName - The name of the event object.
    )
    if not eventObjectHandle:
        error = ctypes.WinError()
        log.error("Unexpected error waiting to register session tracking.")
        return False

    registrationSuccess = ctypes.windll.wtsapi32.WTSRegisterSessionNotification(handle, NOTIFY_FOR_THIS_SESSION)
    ctypes.windll.kernel32.CloseHandle(eventObjectHandle)

    if registrationSuccess:
        log.debug("Registered session tracking")
    else:
        error = ctypes.WinError()
        if error.errno == RPC_S_INVALID_BINDING:
            log.error(
                "WTS registration failed. "
                "Waited successfully on TermSrvReadyEvent to ensure that WTS is ready to allow registration. "
                "Cause of failure unknown. "
            )
        else:
            log.error("Unexpected error registering session tracking.")

    return registrationSuccess


def unregister(handle: HWND) -> None:
    """
    This function must be called once for every call to register.
    If unregistration fails, session tracking may not work properly until the session can be unregistered in a new instance.

    https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsunregistersessionnotification
    """
    if ctypes.windll.wtsapi32.WTSUnRegisterSessionNotification(handle):
        log.debug("Unregistered session tracking")
    else:
        error = ctypes.WinError()
        log.error("Unexpected error unregistering session tracking.")

In your Window Message handler for the window, when you receive WM_WTSSESSION_CHANGE , handle WTS_SESSION_UNLOCK and WTS_SESSION_LOCK events to track the state of Windows being locked. In your Window Message handler for the window, when you receive WM_WTSSESSION_CHANGE , handle WTS_SESSION_UNLOCK and WTS_SESSION_LOCK events to track the state of Windows being locked.

A similar answer here might give more context on handling windows messages .此处类似的答案可能会提供有关处理 windows 消息的更多上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM