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

7 人关注

如何检查一个Windows操作系统工作站是否被锁定? (例如Win+L或在Ctrl+Alt+Del后选择锁定选项。)

我想要类似 ctypes.windll.user32.isWorkstationLocked() 的东西。

2 个评论
它是什么版本的Windows?
下面的答案有什么作用吗?
python
windows
python-3.x
Ivan Baksheev
Ivan Baksheev
发布于 2015-12-30
9 个回答
macok
macok
发布于 2022-08-19
已采纳
0 人赞同

这个代码今天在四个不同的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')

编辑:另外,这个今天也能用。

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.")
    
来自编辑部分的代码对Windows 10 Pro来说就像一个魅力。
编辑代码工作得很好。我想睡眠只是为了让你有时间锁定屏幕和测试。
@Ruben,是的,正是为了这个。很高兴它对你有用!
原始的user32对我来说不起作用--它有时报告为锁定,即使它没有。Windows 10专业版
Budd
这个答案是不正确的。其他窗口如放大镜(Win+U)可以在Windows 10被锁定时成为前景窗口。
Arclight306
Arclight306
发布于 2022-08-19
0 人赞同

我发现的一个黑客方法是用psutil查看运行中的进程,以了解Windows 10是否被锁定。然后,你搜索看看LogonUI.exe是否正在运行。这个进程只在用户有一个锁定会话时运行。

注意:如果你使用切换用户,这个进程将显示为正在运行,这个解决方法将不起作用。Windows实际上产生了多个LogonUI.exe进程,每个登录的锁定用户一个。它只在每次只有一个人登录的情况下有用。

import psutil
for proc in psutil.process_iter():
    if(proc.name() == "LogonUI.exe"):
        print ("Locked")
    
TacomenX
TacomenX
发布于 2022-08-19
0 人赞同

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)
    
@IvanBaksheev,你在使用Python 3吗?这应该写成使用 OpenDesktopW 和明确的unicode字面 u"Default"
注意,"默认 "桌面可能不是活动的应用程序桌面,所以切换到它是一个副作用。我不知道如何获得当前应用程序的桌面。 OpenInputDesktop 试图打开活动桌面,但这可能是 "Winlogon",如果工作站被锁定(需要SYSTEM)。它没有告诉我们WindowStation的活动桌面是什么 应用 winlogon.exe会跟踪这一点,但我不知道有什么API可以查询它。
TheDelta
TheDelta
发布于 2022-08-19
0 人赞同

你可以得到上面的窗口,当会话被锁定时,该函数返回0。

import ctypes
user32 = ctypes.windll.User32
def isLocked():
    return user32.GetForegroundWindow() == 0
    
在Windows 10 Pro中,这对我来说是错误的。当锁定时,hwnd进程ID是一个变化的数字,标题是 "Windows默认锁屏"。只有当我按下回车键输入密码时,才是hwnd == 0。我用这个例子中的几行来获取标题,并将其与0、""或上面的标题进行比较。 pixomania.net/programming/...
@JamesKoss 试试这个下面的解决方案,它对我很有效。
cdonts
cdonts
发布于 2022-08-19
0 人赞同

From the LockWorkStation() 文档 :

没有任何你可以调用的函数来确定工作站是否被锁定。

不是Python的限制,而是系统本身的问题。

Stardidi
Stardidi
发布于 2022-08-19
0 人赞同

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

锁定时返回Windows Default Lock Screen作为窗口标题和C:\Windows\SystemApp\Microsoft.LockApp_<randomcharacters>\LockApp.exe作为文件名。

然而,正如James Koss提到的,如果用户正在输入密码,GetForeGroundWindow将返回0。还有其他(非锁定的)情况,当前的ForegroundWindow是0,所以这不能被依赖。

Budd
这个答案是不正确的。其他窗口如放大镜(Win+U)可以在Windows 10被锁定时成为前景窗口。
Hietsh Kumar
Hietsh Kumar
发布于 2022-08-19
0 人赞同

Hi Check these 4 lines..

返回屏幕上的应用程序名称。如果窗口被锁定,则返回字符串 - Windows 默认锁定屏幕。

from win32gui import GetWindowText, GetForegroundWindow
import time
time.sleep(5)
# lock the system or open the application for a check
print(GetWindowText(GetForegroundWindow()))
    
Budd
这个答案是不正确的。其他窗口如放大镜(Win+U)可以在Windows 10被锁定时成为前景窗口。
Fretxik
Fretxik
发布于 2022-08-19
0 人赞同

根据@Stardidi的回答,这对我来说很有效(Windows 10 Pro)。

import time
import win32gui
import win32api
import win32con
import win32process
while True:
    time.sleep(1)
    _, pid = win32process.GetWindowThreadProcessId(win32gui.GetForegroundWindow())
        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"
    
Budd
Budd
发布于 2022-08-19
0 人赞同

这里没有简单的答案,但你可以通过会话跟踪来做到这一点。

From the LockWorkStation()文档 :

没有你可以调用的函数来确定工作站是否被锁定。要在用户登录时收到通知,请使用 WTSRegisterSessionNotification function to receive wm_wtssession_change 消息。你可以使用会话通知来跟踪桌面状态,这样你就可以知道是否可以与用户互动。

首先,将会话通知注册到你程序的一个窗口。

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: