从服务中获取系统上记录的用户数

时间:2010-10-03 16:47:14

标签: c# windows-services

我想从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,而当我启动服务时,有用户登录?如何在给定时刻获取系统上登录用户的数量? 有办法吗?

2 个答案:

答案 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);
    }
相关问题