【问题标题】:How to detect system idle in windows service?如何在 Windows 服务中检测系统空闲?
【发布时间】:2020-09-14 16:53:59
【问题描述】:

GetLastInputInfo 可以在应用程序上很好地工作,但不能在服务上工作。

GetLastInputInfo 将始终返回 LASTINPUTINFO.dwTime=0,因为它在 Session 0 上运行。

如何实现在Windows服务中检测系统是否空闲?

【问题讨论】:

  • 使用任务计划程序,您可以将任务配置为在 X 分钟不活动后启动。
  • 这个答案没有回答...我想找到一种适合Windows服务的方式。

标签: c++ winapi windows-services


【解决方案1】:

您的服务可以通过WTSEnumerateSessions() 枚举活动会话,通过WTSQuerySessionInformation() 查询每个会话的WTSSessionInfo/Ex。这将为您提供每个会话的LastInputTime(除其他外)。

PWTS_SESSION_INFO sessions = NULL;
DWORD count = 0;

if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count))
{
    DWORD errCode = GetLastError();
    ...
}
else
{
    for (DWORD i = 0; i < count; ++i)
    {
        PWTSINFO info = NULL;
        DWORD size = 0;

        if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessions[i].SessionId, WTSSessionInfo, (LPWSTR*)&info, &size))
        {
            DWORD errCode = GetLastError();
            ...
        }
        else
        {
            // use info->LastInputTime as needed...
            WTSFreeMemory(info);
        }
    }
    WTSFreeMemory(sessions);
}

如果您只对连接到本地机器的物理屏幕/键盘/鼠标的会话感兴趣,您可以使用WTSGetActiveConsoleSessionId() 而不是WTSEnumerateSessions()

【讨论】:

  • 谢谢。我尝试测试它,但我得到的所有值都是零。为什么? ``` while (true) { auto id = WTSGetActiveConsoleSessionId();自动 hServer = WTS_CURRENT_SERVER_HANDLE; DWORD 字节 = 0; WCHAR* buf = NULL;自动 b = WTSQuerySessionInformationW(hServer, id, WTSSessionInfo, &buf, &bytes);自动信息 = (PWTSINFOW)(buf); cout LastInputTime.LowPart LastInputTime.HighPart 状态
  • 在访问返回的数据之前,您没有检查WTSQuerySessionInformationW() 的返回值是否失败。试试这个:while (true) { auto id = WTSGetActiveConsoleSessionId(); if (id != 0xFFFFFFFF) { DWORD bytes = 0; PWTSINFOW info = NULL; if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, id, WTSSessionInfo, (LPWSTR*)&amp;info, &amp;bytes)) { cout &lt;&lt; "LastInputTime: " &lt;&lt; info-&gt;LastInputTime.QuadPart &lt;&lt; endl; cout &lt;&lt; "State: " &lt;&lt; info-&gt;State &lt;&lt; endl; WTSFreeMemory(info); } else { auto errCode = GetLastError(); cout &lt;&lt; "Error: " &lt;&lt; errCode &lt;&lt; endl; } } Sleep(1000); }
  • 我已经检查了所有返回成功的API,没有错误,所以为了简单起见,我不在这里进行错误检查。但是代码仍然在应用程序和 Windows 服务上打印 0。我找不到任何进一步的资源来使它工作。有没有这方面的资源。谢谢
  • WTSSessionInfoEx 有同样的问题吗?如果是这样,那我不知道还能告诉你什么。显然,这是您必须与 Microsoft 讨论的问题。同时,您可以尝试使用WTSQueryUserToken()CreateProcessAsUser() 在每个所需会话中创建一个新进程,让该进程调用GetLastInputInfo(),然后使用IPC 将该信息发送回您的主服务进程。
  • 尝试设置“允许服务与桌面交互”标志。
猜你喜欢
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 2017-12-14
相关资源
最近更新 更多