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

Java中如何检测用户是否尝试锁定Windows系统?

检测Windows锁定操作的Java实现方案

嘿,这个需求我之前帮朋友处理过,在Java里监听Windows的锁屏/解锁事件其实有两种比较靠谱的路子,我给你详细说说:

方法一:用JNA对接Windows系统API(实时事件监听)

这是最推荐的方案,因为它是事件驱动的,能第一时间捕捉到锁屏/解锁动作,完全没有延迟。核心思路是通过JNA调用Windows的WTSRegisterSessionNotification API,监听用户会话状态的变化。

步骤1:引入JNA依赖

如果用Maven管理项目,在pom.xml里添加以下依赖:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>

步骤2:实现监听逻辑

下面是完整的可运行示例代码,注释已经把关键逻辑讲得很清楚了:

import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.W32APIOptions;

public class WindowsLockListener {

    // 定义Windows会话通知的核心消息常量
    private static final int WM_WTSSESSION_CHANGE = 0x02B1;
    private static final int WTS_SESSION_LOCK = 0x7;
    private static final int WTS_SESSION_UNLOCK = 0x8;

    // 扩展User32接口,引入需要的系统API
    public interface MyUser32 extends User32 {
        MyUser32 INSTANCE = Native.load("user32", MyUser32.class, W32APIOptions.DEFAULT_OPTIONS);

        boolean WTSRegisterSessionNotification(WinDef.HWND hWnd, int dwFlags);
        boolean WTSUnRegisterSessionNotification(WinDef.HWND hWnd);
    }

    public static void main(String[] args) {
        // 创建一个隐藏窗口来接收系统消息(Windows要求必须绑定窗口句柄才能监听会话事件)
        WinUser.WNDCLASSEX wClass = new WinUser.WNDCLASSEX();
        wClass.lpfnWndProc = new WinUser.WindowProc() {
            @Override
            public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
                if (uMsg == WM_WTSSESSION_CHANGE) {
                    int eventType = wParam.intValue();
                    switch (eventType) {
                        case WTS_SESSION_LOCK:
                            System.out.println("用户锁定了电脑!执行你的特定操作...");
                            // 在这里编写你需要触发的业务逻辑
                            break;
                        case WTS_SESSION_UNLOCK:
                            System.out.println("用户解锁了电脑!");
                            break;
                    }
                }
                return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
            }
        };
        wClass.lpszClassName = "LockListenerWindowClass";
        User32.INSTANCE.RegisterClassEx(wClass);
        WinDef.HWND hWnd = User32.INSTANCE.CreateWindowEx(0, wClass.lpszClassName, "LockListener", 0, 0, 0, 0, 0, null, null, null, null);

        // 注册会话通知监听
        MyUser32.INSTANCE.WTSRegisterSessionNotification(hWnd, 0);

        // 启动消息循环,保持程序运行以接收系统事件
        WinUser.MSG msg = new WinUser.MSG();
        while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0) != 0) {
            User32.INSTANCE.TranslateMessage(msg);
            User32.INSTANCE.DispatchMessage(msg);
        }

        // 程序退出时注销监听,避免资源泄漏
        MyUser32.INSTANCE.WTSUnRegisterSessionNotification(hWnd);
    }
}

方法二:轮询系统命令(轻量但有延迟)

如果不想引入JNA依赖,也可以通过执行Windows原生的query user命令,解析输出来判断当前会话是否锁定。这种方法是轮询式的,适合对实时性要求不高的场景。

示例代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class LockStatusChecker {

    public static boolean isComputerLocked() throws IOException {
        Process process = new ProcessBuilder("query", "user").start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        boolean isLocked = false;

        // 解析命令输出,不同Windows版本的关键字可能略有差异
        while ((line = reader.readLine()) != null) {
            if (line.contains("Disc") || line.contains("Locked")) {
                isLocked = true;
                break;
            }
        }
        reader.close();
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return isLocked;
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        boolean lastLockStatus = false;
        while (true) {
            boolean currentLockStatus = isComputerLocked();
            if (currentLockStatus && !lastLockStatus) {
                System.out.println("电脑已锁定!执行特定操作...");
                // 执行你的业务逻辑
            }
            lastLockStatus = currentLockStatus;
            Thread.sleep(1000); // 每秒检查一次状态
        }
    }
}

额外注意事项

  • 方法一中的隐藏窗口是必须的,Windows的会话通知机制要求必须绑定到一个窗口句柄才能接收系统消息。
  • 方法二的query user命令在部分Windows家庭版中可能没有权限执行,需要提前测试兼容性。
  • 如果你的工具需要跨平台,记得通过System.getProperty("os.name").toLowerCase().contains("win")判断系统类型,给非Windows系统做兼容处理。

要是你在实现过程中遇到具体问题,比如JNA依赖配置报错、命令解析异常之类的,随时提出来就行!

内容的提问来源于stack exchange,提问作者Shobhit Tyagi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:15:31