我正在编写一个 Windows 服务,它需要知道当前是否有任何用户在机器上登录。
到目前为止,我已经尝试过 Win32_LogonSession
(WMI) 和 LsaEnumerateLogonSessions
/LsaGetLogonSessionData
(secur32.dll)。
两者都有效,并且似乎返回相同的数据,但是当用户注销时它们更新速度太慢:
- 当系统启动时,他们返回“0 个交互用户”。 (好的)
- 当我登录时,他们返回“1 个交互式用户”。 (好的)
- 但是当我注销时,用户数保持为 1。重新登录后,用户数为 2,依此类推。
因此 Win32_LogonSession 和 LsaEnumerateLogonSessions 都足够好。 服务需要在最后一个交互用户离开后 5 分钟内知道。
甚至 SysInternals 的 LogonSessions.exe 也没有给出最新的答案。
此外,答案不能是“监视登录和注销事件并具有计数器变量”,因为服务可以随时启动。
最佳答案
我最终采用了以下方法:计算至少有一个进程在运行的交互式 session 的数量。
1) 获取每个交互 session 的登录 session 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) 获取每个正在运行的进程的登录 session ID。
[首先我们需要为当前应用启用SeDebugPrivilege。]
- GetCurrentProcess (kernel32.dll)
- OpenProcessToken TOKEN_ADJUST_PRIVILEGES (advapi32.dll)
- LookupPrivilegeValue SE_DEBUG_NAME (advapi32.dll)
- AdjustTokenPrivileges (advapi32.dll)
- 关闭句柄 (kernel32.dll)
[然后检索我们想要的数据。]
- 枚举进程 (psapi.dll)
- OpenProcess PROCESS_QUERY_INFORMATION (kernel32.dll)
- OpenProcessToken TOKEN_QUERY (advapi32.dll)
- GetTokenInformation TOKEN_INFORMATION_CLASS.TokenStatistics (advapi32.dll)
- accessTokenStatistics .AuthenticationId <- 将此值保存在 LUID 集中。
- 关闭句柄 (kernel32.dll)
3) 设置交集基数
interactiveSessionsCount = | { sessionData.LoginID } ∩ { accessTokenStatistics.AuthenticationId } |
观察:sessionData.LoginID 和 accessTokenStatistics.AuthenticationId 都是 LUID 类型.
关于windows - 如何在 Windows 中获取当前的交互式用户 session 数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6255424/