如何用Go语言判断Windows系统的屏幕是否锁定?
Go语言实现Windows屏幕锁定状态检测的优化方案
问题描述
使用WinAPI实现Windows锁屏检测时,原有代码存在判断不准确的问题:
- 当触发Ctrl+Alt+Del或UAC提示时,能正确返回
LockDesktop = true - 但使用Win+L锁定屏幕时,返回
LockDesktop = false,只有调出密码输入界面后才会正确识别
原有实现代码:
const DESKTOP_SWITCHDESKTOP = 0x0100 func main() { for range time.Tick(time.Second) { fmt.Println("LockDesktop = ", LockDesktop()) } } func LockDesktop() bool { h := winApi.OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP) defer winApi.CloseDesktop(h) if h != 0 { return !winApi.SwitchDesktop(h) } return false }
问题根源
SwitchDesktop的判断逻辑是:当进程无法切换到指定桌面时返回失败。但Win+L锁定后,系统会创建独立的WinSta0\Winlogon工作站,此时默认桌面仍存在且SwitchDesktop调用依然能成功,导致返回错误的false。
可行解决方案
方案1:窗口标题匹配(用户自行实现)
通过获取前台窗口标题判断锁屏状态,代码如下:
func main() { for range time.Tick(time.Second) { fmt.Println("LockDesktop = ", LockDesktop() || IsDefaultLockScreen()) } } func IsDefaultLockScreen() bool { hwnd := GetForegroundWindow() windowText := GetWindowText(hwnd) return windowText == "Windows Default Lock Screen" }
⚠️ 局限性:该方法依赖系统语言,非英文系统的锁屏窗口标题会不同(比如中文系统为「Windows 默认锁屏」),需要根据目标系统语言调整判断字符串。
方案2:基于会话状态的WinAPI检测(推荐)
直接调用WTSQuerySessionInformation查询系统会话状态,准确性不受语言影响,实现代码如下:
首先定义所需的WinAPI绑定:
import ( "syscall" "unsafe" ) var ( kernel32 = syscall.MustLoadDLL("kernel32.dll") wtsapi32 = syscall.MustLoadDLL("wtsapi32.dll") getCurrentProcessId = kernel32.MustFindProc("GetCurrentProcessId") wtsQuerySessionInformation = wtsapi32.MustFindProc("WTSQuerySessionInformationW") wtsFreeMemory = wtsapi32.MustFindProc("WTSFreeMemory") ) // IsSessionLocked 检测当前会话是否处于锁定状态 func IsSessionLocked() bool { // 获取当前进程ID pid, _, _ := getCurrentProcessId.Call() var pBuffer uintptr var bytesReturned uint32 // WTS_SESSIONSTATE = 11,查询会话状态 res, _, _ := wtsQuerySessionInformation.Call( 0, uint32(pid), 11, uintptr(unsafe.Pointer(&pBuffer)), uintptr(unsafe.Pointer(&bytesReturned)), ) if res == 0 { return false } defer wtsFreeMemory.Call(pBuffer) // WTS_SESSIONSTATE_LOCKED 对应值为 4 sessionState := *(*uint32)(unsafe.Pointer(pBuffer)) return sessionState == 4 }
主函数调用示例:
func main() { for range time.Tick(time.Second) { fmt.Println("LockDesktop = ", IsSessionLocked()) } }
该方法直接读取系统会话的锁定状态,适用于所有语言版本的Windows系统,判断结果更可靠。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

