2010-10-03 64 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); 
    } 
相關問題