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

Rust调用winapi的GetLastInputInfo无法正确检测系统空闲时长

问题原因与解决方案

你的代码核心问题是使用了32位的GetTickCount()函数,它的返回值(DWORD类型)每49.7天会溢出并重置为0。当系统运行时间超过这个时长后,now(当前GetTickCount()的返回值)会远小于last_input_info.dwTime(溢出前记录的最后输入时间)。由于两者都是无符号32位整数,减法运算会触发无符号绕回,最终得到的差值会是一个极小的数值(0~31ms左右),完全不符合实际的空闲时长。

你提到的音频流问题和当前异常无关:powercfg -requests中显示的音频流仅用于阻止系统进入睡眠状态,不会模拟输入事件,因此不是导致你代码失效的原因。

修改后的代码

将GetTickCount()替换为64位的GetTickCount64()函数,它返回的ULONGLONG类型不会有溢出问题,能正确计算系统启动后的毫秒数:

use winapi::um::{
    winuser::{
        LASTINPUTINFO,
        PLASTINPUTINFO,
        GetLastInputInfo
    },
};

fn sleep(milliseconds: u64){
    let mills = std::time::Duration::from_millis(milliseconds);
    std::thread::sleep(mills);
}

fn main() {
    loop {
        // 使用64位的GetTickCount64替代32位的GetTickCount
        let now = unsafe { winapi::um::sysinfoapi::GetTickCount64() };
        let mut last_input_info = LASTINPUTINFO {
            cbSize: std::mem::size_of::<LASTINPUTINFO>() as u32,
            dwTime: 0
        };

        let p_last_input_info: PLASTINPUTINFO = &mut last_input_info as *mut LASTINPUTINFO;

        let ok = unsafe { GetLastInputInfo(p_last_input_info) } != 0;

        let logvar = match ok {
            true => {
                // 将dwTime转换为u64类型后计算差值
                let millis = now - last_input_info.dwTime as u64;
                Ok(std::time::Duration::from_millis(millis))
            },
            false => Err(format!("GetLastInputInfo failed"))
        }.unwrap();

        println!("{:?}", logvar);
        sleep(1000);
    };
}

关键修改点

  • 替换GetTickCount()为GetTickCount64(),避免32位整数溢出问题
  • 计算差值时将last_input_info.dwTime(32位DWORD)转换为u64,与GetTickCount64()的返回值类型匹配

内容的提问来源于stack exchange,提问作者Gabriel Akonom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:45:30