为什么 GetLastInputInfo() 不会返回我正在模拟的用户的信息?
摘要
解释了 GetLastInputInfo() 在模拟情况下无法工作,因为它返回的是调用会话的数据,而不是被模拟用户的数据;要获取另一个会话的最后输入时间,必须在该会话中使用辅助进程。
<p>一位客户有一个 Windows NT 服务进程,他们想通过该服务进程获取所有已登录用户的最后输入时间。他们的策略是使用 <code>WTSQueryUserToken()</code> 获取每个用户的令牌,然后使用该令牌模拟该用户,再调用 <code>GetLastInputInfo()</code> 获取该用户的最后输入时间。不幸的是,该函数总是返回服务会话的最后输入信息,而且由于服务是非交互的,它总是报告自系统启动以来没有任何输入。</p>
<p><code>GetLastInputInfo()</code> 是否支持模拟操作?</p>
<p>回想一下,<a title="模拟时此操作是否有效?默认答案为否" href="https://devblogs.microsoft.com/oldnewthing/20110928-00/?p=9533">对于“模拟时此操作是否有效?”的默认答案是“否”</a>。事实上,如果你仔细阅读 <code>GetLastInputInfo()</code> 的文档,它明确说明了这一点。</p>
<blockquote class="q"><p>此函数对于输入空闲检测非常有用。然而,<b>GetLastInputInfo</b> 并不提供跨所有运行会话的系统级用户输入信息。相反,<b>GetLastInputInfo</b> 提供的是会话特定的用户输入信息,<u>仅针对调用该函数的会话</u>。</p></blockquote>
<p>我强调了重要部分。它报告的是调用该函数的会话的最后输入信息。当服务模拟用户时,它会更新其安全上下文以与被模拟用户保持一致,但这并不能改变它仍然在会话零(即服务会话)中运行的事实。</p>
<p>如果你需要从另一个会话获取最后输入信息,你需要在那个会话中有一个“朋友”来为你调用它。通常的做法是在目标会话中启动一个辅助进程:该辅助进程收集你需要的信息,然后将信息发送给服务。</p>
<p><b>额外闲谈</b>:一个相关的问题是“服务中的 <code>GetAsyncKeyState</code> 是否有效?”答案是技术上有效。不过,它可能并非你所想的那样工作。它返回的是服务所在桌面的异步按键状态。由于服务在非交互式会话中运行,该桌面永远不会看到任何键盘活动。</p>
<p>本文《<a href="https://devblogs.microsoft.com/oldnewthing/20260618-00/?p=112444">为什么 <CODE>GetLastInputInfo()</CODE> 不会返回我正在模拟的用户的信息?</a>》最早出现在 <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a> 上。</p>
查看缓存全文
缓存时间: 2026/06/20 14:22
# 为什么 `GetLastInputInfo()` 不会返回我正在模拟的用户的信息? - 旧事新说
来源:https://devblogs.microsoft.com/oldnewthing/20260618-00?p=112444
一位客户有一个 Windows NT 服务进程,并且他们想从该服务进程中获取所有已登录用户的最后输入时间。他们的策略是使用 `WTSQueryUserToken()` 获取每个用户的令牌,使用该令牌模拟该用户,然后调用 `GetLastInputInfo()` 来获取该用户的最后输入时间。不幸的是,该函数始终返回服务会话的最后输入信息,而由于服务不是交互式的,它总是显示自系统启动以来没有输入。
`GetLastInputInfo()` 是否支持模拟?
回想一下,“在模拟时,这能工作吗?” 的默认答案是“不行”(https://devblogs.microsoft.com/oldnewthing/20110928-00/?p=9533)。事实上,`GetLastInputInfo()` 的文档如果仔细阅读,会明确说明它不支持。
> 此函数可用于输入空闲检测。但是,**GetLastInputInfo** 不提供跨所有运行会话的系统范围用户输入信息。相反,**GetLastInputInfo** 仅针对调用该函数的会话提供会话特定的用户输入信息。
我强调了重要部分。它报告的是调用该函数的会话的最后输入信息。当服务进行模拟时,它会更新其安全上下文以匹配被模拟的用户,但这并不能改变它仍然在会话零(服务会话)中运行的事实。
如果你需要从另一个会话获取最后输入信息,你需要该会话中的一个“朋友”来替你调用它。通常,这是通过将一个辅助进程启动到目标会话中来完成的:该辅助进程收集你想要的信息,然后将信息发送给服务。
**额外讨论**:一个相关的问题是“服务中能否使用 `GetAsyncKeyState`?” 从技术上讲,答案是肯定的,它可以工作。然而,它可能不像你想的那样工作。它返回服务运行所在桌面的异步键状态。由于服务运行在非交互式会话中,该桌面永远不会看到任何键盘活动。
### 类别
## 作者
Raymond Chen
Raymond 参与 Windows 的发展已有 30 多年。2003 年,他创办了一个名为“旧事新说”的网站,其受欢迎程度远远超出了他最疯狂的想象,这一发展至今仍让他感到后怕。该网站催生了一本书,巧合的是,书名也是《旧事新说》(Addison Wesley 2007)。他偶尔会出现在 Windows Dev Docs Twitter 账号上,讲述一些不提供有用信息的故事。
相似文章
倾听的幻象
本文分析了“倾听的幻象”这一心理现象:用户因语言线索而感知到AI具有共情能力,尽管AI并不具备真正的理解力。文章提出了设计指南,以确保透明度并防止用户将人际连接的需求外包给自动化系统。
我的AI智能体自信地给出了完全错误的信息。以下是我的收获。
一位开发者分享了其AI智能体产生幻觉数据的亲身经历,以及关于验证和提示具体性的教训。
用户更改键盘布局时程序挂起的问题
一个调试故事,讲述了当用户更改键盘布局(例如使用 Win+Space 快捷键)时,Windows 程序挂起的原因,是由于一个后台线程创建了窗口但没有泵送消息。修复方法是要么泵送消息,要么销毁窗口。
ChatGPT 计算机使用:现在支持更快的实时画中画
OpenAI 宣布了更快的 ChatGPT 计算机使用版本,支持实时画中画,但提供的记录缺乏技术细节。
一位客户投诉我们智能体三周前所说的内容,但我们无法还原当时情况
一家公司讲述了一起客户投诉AI智能体输出错误内容的事件,但由于版本管理不善,他们无法还原确切的提示词和模型版本,凸显了AI部署中需要更好的可追溯性。