How to get the current number of interactive user sessions in Windows?

浪尽此生 提交于 2019-11-30 16:06:32

问题


I'm writing a Windows service that needs to know whether there are any users currently logged-on in the machine.

So far I've tried Win32_LogonSession (WMI), and LsaEnumerateLogonSessions/LsaGetLogonSessionData (secur32.dll).

Both work, and seem to return the same data, but they are too slow to update when a user log off:

  • When the system starts, they return "0 interactive users". (OK)
  • When I log on, they return "1 interactive user". (OK)
  • But then when I log off, the number of users is kept at 1. After a new log-on, the number is 2, and so on.

Thus Win32_LogonSession nor LsaEnumerateLogonSessions are good enough. The service needs to know within 5 minutes after the last interactive user leaves.

Not even SysInternals' LogonSessions.exe gives up-to-date answers.
Also, the answer cannot be "monitor logon and logoff events and have a counter variable", because the service can be started at any time.


回答1:


I ended up with the following approach: count the number of interactive sessions which have at least one process running.

1) Get the logon session id for each interactive session.

  • LsaEnumerateLogonSessions (secur32.dll)
  • LsaGetLogonSessionData (secur32.dll)
  • sessionData.LogonType = SECURITY_LOGON_TYPE.Interactive or sessionData.LogonType = SECURITY_LOGON_TYPE.RemoteInteractive
  • sessionData.LoginID <- Keep this value in a LUID set.
  • LsaFreeReturnBuffer (secur32.dll)

2) Get the logon session id for each running process.

[First we need to enable the SeDebugPrivilege to the current application.]

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

[Then retrieve the data we want.]

  • EnumProcesses (psapi.dll)
  • OpenProcess PROCESS_QUERY_INFORMATION (kernel32.dll)
  • OpenProcessToken TOKEN_QUERY (advapi32.dll)
  • GetTokenInformation TOKEN_INFORMATION_CLASS.TokenStatistics (advapi32.dll)
  • accessTokenStatistics.AuthenticationId <- Keep this value in a LUID set.
  • CloseHandle (kernel32.dll)

3) Sets intersection cardinality

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

Obs: sessionData.LoginID and accessTokenStatistics.AuthenticationId are both of type LUID.



来源:https://stackoverflow.com/questions/6255424/how-to-get-the-current-number-of-interactive-user-sessions-in-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!