2010-10-03 98 views
1

我想从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手动地从用户会话和不启动该服务,而当我推出的服务有一个用户登录?我怎样才能获得系统在特定时刻登录用户的数量? 有没有办法做到这一点?

回答

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数组以避免泄漏。 ()也返回非交互式会话,所以你需要在每个LUID上调用LsaGetLogonSessionData()来检查它是否是交互式的。所以最好使用像Unmesh建议的WMI,因为您不必遍历IntPtr。但算法保持不变。

+0

我只有一个用户登录系统和logonSessionCount还给我6 ...为什么? – aleroot 2010-10-03 17:20:30

+0

@aleroot,看起来像非交互式会话也会返回。您可以使用LsaGetLogonSessionData()过滤会话列表,但这会变得相当复杂,只是为了获得用户数量... – 2010-10-03 17:26:43

+0

请检查该方法的文档,可能计数包括其他登录类型,而不是交互式服务,网络等等 – 2010-10-03 17:29:56

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); 
    }