关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。我们确认了 Microsoft Win32 API 的 GetLastInputInfo 规范,并将其整理为一个最小尝试,通过 PowerShell P/Invoke 来观察距离上次输入所经过的时间。
验证状态:📘 已确认 Microsoft 官方规范・Windows 实机未验证
从 PowerShell 调用 Win32 GetLastInputInfo 时,可以根据键盘和鼠标的最后输入时间来观察“没有输入操作持续了多久”。
本次如果能以数值形式获取到 IdleSeconds(闲置秒数),即代表尝试成功。
冒烟测试
Add-Type @'
using System;
using System.Runtime.InteropServices;
public static class InputIdle {
[StructLayout(LayoutKind.Sequential)]
public struct LASTINPUTINFO { public uint cbSize; public uint dwTime; }
[DllImport("user32.dll")]
public static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
}
'@
$lii = New-Object InputIdle+LASTINPUTINFO
$lii.cbSize = [Runtime.InteropServices.Marshal]::SizeOf($lii)
if ([InputIdle]::GetLastInputInfo([ref]$lii)) {
$now32 = [uint32]([Environment]::TickCount64 -band 0xFFFFFFFFL)
$idleMs = [uint32]($now32 - $lii.dwTime)
"[SUCCESS] IdleSeconds = {0:N1}" -f ($idleMs / 1000)
} else {
$code = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
"[FAILED] GetLastInputInfo returned false. Win32Error=$code"
}
观察
确认数值后,请保持几秒钟不碰鼠标和键盘并重新运行。接着移动鼠标再次运行,观察数值是否变小。
为什么能获取到
Windows 保存了输入事件的时间信息,该 API 返回当前会话的最后输入信息。这并非考勤或证明“本人当时在工作”的依据。
dwTime 由于是 32 位 tick 值,因此在优化版本中,当前的 tick 值也被调整到了 32 位空间来计算差值。注意 API 返回的类型以及在 PowerShell 侧计算的类型,是本次尝试中更深一层要点。
修改一处
仅将显示单位从秒更改为分钟。
$idleMs / 60000
在 Daily-Code-Samples 版本中,使其能够通过 -Unit Seconds / -Unit Minutes 进行切换,同时还可以确认原始的毫秒数、LastInputTick 和 CurrentTick32。
失败与边界
需要注意会话、tick 计数的处理以及类型转换。如果 API 返回 false,则不能视作成功,同时还会显示 Win32 错误。切勿将该数值过度解读用于监视用途,这一点也很重要。
如果要在工作中使用
它可以用于个人本地工具中的辅助判定,例如“如果在一定时间内没有输入,则开始执行较重的自动处理”。例如,在开始大量 CSV 文件的本地聚合之前的辅助条件,或是演示终端显示切换的实验。
另一方面,请勿将其轻易挪用于员工监控或考勤判定。没有输入并不等同于没有工作,该 API 无法证明实际的工作情况。
官方资料
- Microsoft Learn: GetLastInputInfo function

