You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:31:01