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
相关产品推荐
相关产品推荐

