如何在Windows中获取当前的交互式用户会话数量?

我正在编写一个Windows服务,需要知道当前是否有任何用户在机器上login。

到目前为止,我已经尝试过Win32_LogonSession (WMI)和LsaEnumerateLogonSessions / LsaGetLogonSessionData (secur32.dll)。

这两个工作,似乎都返回相同的数据,但它们太慢,无法更新时,用户注销:

  • 系统启动时,返回“0个交互式用户”。 (好)
  • 当我login时,他们返回“1交互式用户”。 (好)
  • 但是,当我注销时,用户数保持为1.新login后,数为2,依此类推。

因此Win32_LogonSession和LsaEnumerateLogonSessions都不够好。 在最后一个交互式用户离开后的5分钟内,该服务需要知道。

SysInternals的LogonSessions.exe甚至没有提供最新的答案。
此外,答案不能是“监视login和注销事件,并有一个计数器variables”,因为服务可以在任何时候启动。

我结束了以下方法:计数至少有一个进程正在运行的交互式会话的数量。

1)获取每个交互式会话的登录会话ID。

  • LsaEnumerateLogonSessions(secur32.dll)
  • LsaGetLogonSessionData(secur32.dll)
  • sessionData .LogonType = SECURITY_LOGON_TYPE.Interactive或sessionData.LogonType = SECURITY_LOGON_TYPE.RemoteInteractive
  • sessionData.LoginID < – 将此值保存在LUID集中。
  • LsaFreeReturnBuffer(secur32.dll)

2)获取每个正在运行的进程的登录会话ID。

[首先我们需要启用SeDebugPrivilege到当前的应用程序。]

  • GetCurrentProcess(kernel32.dll)
  • OpenProcessToken TOKEN_ADJUST_PRIVILEGES (advapi32.dll)
  • LookupPrivilegeValue SE_DEBUG_NAME (advapi32.dll)
  • AdjustTokenPrivileges(advapi32.dll)
  • CloseHandle(kernel32.dll)

[然后检索我们想要的数据。]

  • EnumProcesses(psapi.dll)
  • OpenProcess PROCESS_QUERY_INFORMATION (kernel32.dll)
  • OpenProcessToken TOKEN_QUERY (advapi32.dll)
  • GetTokenInformation TOKEN_INFORMATION_CLASS.TokenStatistics (advapi32.dll)
  • accessTokenStatistics .AuthenticationId < – 将此值保存在LUID集中。
  • CloseHandle(kernel32.dll)

3)设置交叉点基数

 interactiveSessionsCount = | { sessionData.LoginID } ∩ { accessTokenStatistics.AuthenticationId } | 

Obs:sessionData.LoginID和accessTokenStatistics.AuthenticationId都是类型LUID 。