我想从Windows服务(本地系统帐户)中了解系统上已登录用户的数量,我已经在我的Windows服务上实现了这个方法:
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
switch (changeDescription.Reason)
{
case SessionChangeReason.SessionLogon:
userCount += 1;
break;
case SessionChangeReason.SessionLogoff:
userCount -= 1;
break;
case SessionChangeReason.RemoteConnect:
userCount += 1;
break;
case SessionChangeReason.RemoteDisconnect:
userCount -= 1;
break;
default:
break;
}
}
问题是如果我从用户会话手动启动此服务而不是在系统启动时,变量userCount = 0,而当我启动服务时,有用户登录?如何在给定时刻获取系统上登录用户的数量? 有办法吗?
答案 0 :(得分:1)
您可以p / invoke LsaEnumerateLogonSessions():
[DllImport("Secur32.dll", SetLastError = false)]
private static extern uint LsaEnumerateLogonSessions(out UInt64 logonSessionCount, out IntPtr logonSessionList);
[DllImport("secur32.dll", SetLastError = false)]
private static extern uint LsaFreeReturnBuffer(IntPtr buffer);
如果函数成功,第一个参数将包含已登录用户的计数。您应该立即使用LsaFreeReturnBuffer()释放第二个参数中返回的LUID数组,以避免泄漏。
编辑: LsaEnumerateLogonSessions()也返回非交互式会话,因此您需要在每个LUID上调用LsaGetLogonSessionData()来检查它是否是交互式的。因此,最好使用像Unmesh建议的WMI,因为您不必迭代IntPtr。但算法保持不变。
答案 1 :(得分:1)
这是一个古老的主题,但我想发布这个以防任何人需要其他信息。我发现这篇文章展示了如何使用LsaEnumerateLogonSessions,以及使用System.Management的代码。
对于LsaEnumerateLogonSessions:
http://www.codeproject.com/Articles/18179/Using-the-Local-Security-Authority-to-Enumerate-Us
对于System.Management:
System.Management.ConnectionOptions connOptions = new System.Management.ConnectionOptions();
System.Collections.Generic.List<string> sessionIDs = new System.Collections.Generic.List<string>();
connOptions.Impersonation = System.Management.ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
try
{
//Use "." for the local computer, or a computer name or IP address for a remote computer.
string compName = ".";
System.Management.ManagementScope manScope =
new System.Management.ManagementScope(
String.Format(@"\\{0}\ROOT\CIMV2", compName), connOptions);
manScope.Connect();
System.Management.SelectQuery selectQuery = new System.Management.SelectQuery("Select SessionId from Win32_Process");
using (System.Management.ManagementObjectSearcher searcher =
new System.Management.ManagementObjectSearcher(manScope, selectQuery))
{
foreach (System.Management.ManagementObject proc in searcher.Get())
{
string id = proc["SessionId"].ToString();
//Skip session 0, which is the system session.
if (id != "0")
{
sessionIDs.Add(id);
}
}
}
//remove the dups.
sessionIDs = sessionIDs.Distinct().ToList();
foreach (string id in sessionIDs)
{
System.Diagnostics.Debug.Print(id);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.Print(ex.Message);
}