2011-06-24 31 views
5

在Web應用程序中,我們正在尋找顯示特定組成員的用戶的sam帳戶列表。在許多情況下,組可能擁有500個或更多成員,我們需要該頁面具有響應能力。使用C#獲取Active Directory中組成員列表的快速方法

約500名成員組成的團隊需要7-8秒才能獲得該組所有成員的sam帳戶列表。有更快的方法嗎?我知道Active Directory管理控制檯不到一秒鐘就完成了。

我已經嘗試了一些方法:

1)

PrincipalContext pcRoot = new PrincipalContext(ContextType.Domain) 
GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcRoot, "MyGroup"); 
List<string> lst = grp.Members.Select(g => g.SamAccountName).ToList(); 

2)

PrincipalContext pcRoot = new PrincipalContext(ContextType.Domain) 
GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcRoot, "MyGroup"); 
PrincipalSearchResult<Principal> lstMembers = grp.GetMembers(true); 
List<string> lst = new List<string>(); 
foreach (Principal member in lstMembers) 
{ 
    if (member.StructuralObjectClass.Equals("user")) 
    { 
     lst.Add(member .SamAccountName); 
    } 
} 

3)

PrincipalContext pcRoot = new PrincipalContext(ContextType.Domain) 
GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcRoot, "MyGroup"); 
System.DirectoryServices.DirectoryEntry de = (System.DirectoryServices.DirectoryEntry)grp.GetUnderlyingObject(); 
List<string> lst = new List<string>(); 
foreach (string sDN in de.Properties["member"]) 
{ 
    System.DirectoryServices.DirectoryEntry deMember = new System.DirectoryServices.DirectoryEntry("LDAP://" + sDN); 
    lst.Add(deMember.Properties["samAccountName"].Value.ToString()); 
} 

回答

0

你試過LDAP查詢?該頁面的底部有一個C#中的例子,用於通過組枚舉來獲取成員。 MSDN BOL

using System; 
using System.DirectoryServices; 

namespace ADAM_Examples 
{ 
class EnumMembers 
{ 
    /// <summary> 
    /// Enumerate AD LDS groups and group members. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     DirectoryEntry objADAM;     // Binding object. 
     DirectoryEntry objGroupEntry;    // Group Results. 
     DirectorySearcher objSearchADAM;   // Search object. 
     SearchResultCollection objSearchResults; // Results collection. 
     string strPath;       // Binding path. 

     // Construct the binding string. 
     strPath = "LDAP://localhost:389/OU=TestOU,O=Fabrikam,C=US"; 
     Console.WriteLine("Bind to: {0}", strPath); 
     Console.WriteLine("Enum: Groups and members."); 

     // Get the AD LDS object. 
     try 
     { 
      objADAM = new DirectoryEntry(strPath); 
      objADAM.RefreshCache(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Error: Bind failed."); 
      Console.WriteLine("   {0}", e.Message); 
      return; 
     } 

     // Get search object, specify filter and scope, 
     // perform search. 
     try 
     { 
      objSearchADAM = new DirectorySearcher(objADAM); 
      objSearchADAM.Filter = "(&(objectClass=group))"; 
      objSearchADAM.SearchScope = SearchScope.Subtree; 
      objSearchResults = objSearchADAM.FindAll(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Error: Search failed."); 
      Console.WriteLine("   {0}", e.Message); 
      return; 
     } 

     // Enumerate groups and members. 
     try 
     { 
      if (objSearchResults.Count != 0) 
      { 
       foreach(SearchResult objResult in objSearchResults) 
       { 
        objGroupEntry = objResult.GetDirectoryEntry(); 
        Console.WriteLine("Group {0}", 
         objGroupEntry.Name); 
        foreach(object objMember 
         in objGroupEntry.Properties["member"]) 
        { 
         Console.WriteLine(" Member: {0}", 
          objMember.ToString()); 
        } 
       } 
      } 
      else 
      { 
       Console.WriteLine("Results: No groups found."); 
      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Error: Enumerate failed."); 
      Console.WriteLine("   {0}", e.Message); 
      return; 
     } 

     Console.WriteLine("Success: Enumeration complete."); 
     return; 
    } 
} 

}

+0

這與我的問題中的例3類似,需要記錄時間的部分是通過成員屬性中的每個項目進行交互。 – Jeremy

+0

必須愛匈牙利符號,從一個原始示例 –

5

我的一個同事使用各種活動目錄檢索方法時,曾與查詢時間類似的問題。他最終將信息緩存在數據庫中,每晚刷新一次,然後訪問數據庫。

考慮到用戶帳戶不會經常改變的事實,這對他來說是一個可以接受的折中方案。根據您的使用情況,這可能會也可能不會被接受。

4

這是一個使用ADSI的遞歸搜索(在嵌套組中搜索用戶)。

static void Main(string[] args) 
{ 
    /* Connection to Active Directory 
    */ 
    string sFromWhere = "LDAP://SRVENTR2:389/dc=societe,dc=fr"; 
    DirectoryEntry deBase = new DirectoryEntry(sFromWhere, "societe\\administrateur", "test.2011"); 

    /* To find all the users member of groups "Grp1" : 
    * Set the base to the groups container DN; for example root DN (dc=societe,dc=fr) 
    * Set the scope to subtree 
    * Use the following filter : 
    * (member:1.2.840.113556.1.4.1941:=CN=Grp1,OU=MonOu,DC=X) 
    */ 
    DirectorySearcher dsLookFor = new DirectorySearcher(deBase); 
    dsLookFor.Filter = "(&(memberof:1.2.840.113556.1.4.1941:=CN=Grp1,OU=MonOu,DC=societe,DC=fr)(objectCategory=user))"; 
    dsLookFor.SearchScope = SearchScope.Subtree; 
    dsLookFor.PropertiesToLoad.Add("cn"); 
    dsLookFor.PropertiesToLoad.Add("samAccountName"); 

    SearchResultCollection srcUsers = dsLookFor.FindAll(); 

    /* Just show each user 
    */ 
    foreach (SearchResult srcUser in srcUsers) 
    { 
    Console.WriteLine("{0}", srcUser.Path); 
    Console.WriteLine("{0}", srcUser.Properties["samAccountName"][0]); 
    } 

    Console.ReadLine(); 
} 
+1

一些古體剩餘的主要原因之一,這是因爲AccountManagement的表現很差。真正獲得AD搜索性能的唯一方法是下移到DirectoryServices庫。笨重的API,但真的很快 –

1

試試這個不知道,如果這將是任何更快,但是....

 PrincipalContext pcRoot = new PrincipalContext(ContextType.Domain) 

     GroupPrincipal mygroup = new GroupPrincipal(pcRoot); 

     // define the principal searcher, based on that example principal 

     PrincipalSearcher ps = new PrincipalSearcher(mygroup); 

     ps.QueryFilter = new GroupPrincipal(pcRoot) { SamAccountName = "Name of your group Case Sensitive" }; 

     List<UserPrincipal> users = new List<UserPrincipal>(); 
     // loop over all principals found by the searcher 

     GroupPrincipal foundGroup = (GroupPrincipal)ps.FindOne(); 

foreach (UserPrincipal u in foundGroup.Members) 
        { 
         users.Add(u); 

        } 
//OR 
List<string> lst = foundGroup.Members.Select(g => g.SamAccountName).ToList();//this will only get the usernames not the user object or UserPrincipal 
0

你的第一個選項類似,我創建從列表中的HashSet。組越大,驗證成員資格所需的時間越長。但是,成功和不成功的成員資格查詢是一致的。如果帳戶不是成員,則通過大型團隊迭代的時間可能會延長3倍,而此方法每次都是相同的。

using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
using(GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "groupName")) 
{ 
    List<string> members = group.GetMembers(true).Select(g => g.SamAccountName).ToList(); 
    HashSet<string> hashset = new HashSet<string>(members, StringComparer.OrdinalIgnoreCase); 

    if(hashset.Contains(someUser) 
     return true; 
} 
相關問題