1

指定されたドメインからユーザーのリストを取得する必要があるアプリケーションを作成しています。これでユーザーを取得できますが、特に大規模なドメインでこれをより速く行うにはどうすればよいですか?

using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
        {
            UserPrincipal userPrincipal = new UserPrincipal(pc);

            PrincipalSearcher search = new PrincipalSearcher(userPrincipal);

            PrincipalSearchResult<Principal> results = search.FindAll();

            foreach (var principals in results.Partition(20))
            {
                IDictionary<string, string> users = new Dictionary<string, string>(20);
                foreach (UserPrincipal principal in principals.Cast<UserPrincipal>())
                {
                    users.Add(principal.SamAccountName, principal.DisplayName);
                }

                yield return users;
            }
        }

基本的に、外側の foreach ループで、IEnumerable> の IEnumerable を取得しています。私はそれを行ったので、一度にいくつかを段階的にロードして、残りがまだロードされている間にそれらをユーザーに表示しようとしましたが、その内部ループにヒットすると、数分間ハングします。

ドメイン\ユーザー名形式でもユーザー名を取得しようとしていますが、その方法もわかりません。

4

3 に答える 3

2

これを試して。より速く動作するはずです。

using System.DirectoryServices;

string[] RetProps = new string[] { "SamAccountName", "DisplayName" };
                //IDictionary<string, string> users = new Dictionary<string, string>();
List<string[]> users = new List<string[]>();

           foreach (SearchResult User in GetAllUsers("YourDomain", RetProps))
           {
            DirectoryEntry DE = User.GetDirectoryEntry();
            try
               {
                users.Add(new string[]{DE.Properties["SamAccountName"][0].ToString(), DE.Properties["DisplayName"][0].ToString()});
               }
               catch
               {
               }
            }


    internal static SearchResultCollection GetAllUsers(string DomainName, string[] Properties)
    {
      DirectoryEntry DE = new DirectoryEntry("LDAP://" + DomainName);
      string Filter = "(&(objectCategory=organizationalPerson)(objectClass=User))";
      DirectorySearcher DS = new DirectorySearcher(DE);
      DS.PageSize = 10000;
      DS.SizeLimit = 10000;
      DS.SearchScope = SearchScope.Subtree;
      DS.PropertiesToLoad.AddRange(Properties); DS.Filter = Filter;
      SearchResultCollection RetObjects = DS.FindAll();
      return RetObjects;
    }
  }
}
于 2012-11-23T10:24:51.090 に答える
0

これはかなり速いです。数秒で 14,000 件の結果が得られました。UI を更新する必要がある場合は、イベント ハンドラと別のスレッドを使用できます。

  string groupName = "Domain Users";
            string domainName = "domain";
            var results = new List<string>();
            using (var pc = new PrincipalContext(ContextType.Domain, domainName))
            {
                using (var grp = GroupPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, groupName))
                {
                    if (grp != null)
                        foreach (var p in grp.GetMembers(false))
                        {
                            results.Add(p.DisplayName);
                        }
                }
                Assert.IsTrue(results.Count > 0);
            }
于 2012-11-21T15:51:38.157 に答える
0

dc はドメイン コントローラです。たとえば、「company.com」です。

public static ArrayList GetAllActiveDirectoryUsersByDisplayName(string dc) 
            {
                ArrayList list = new ArrayList();

                PrincipalContext ctx = new PrincipalContext(ContextType.Domain, dc);
                UserPrincipal u = new UserPrincipal(ctx);

                PrincipalSearcher ps = new PrincipalSearcher(u);
                PrincipalSearchResult<Principal> results = ps.FindAll();

                foreach (UserPrincipal usr in results)
                {
                    list.Add(usr.Name);
                }

            list.Sort();

            return list; 
        }

エンドフロントでこれを行うことができます:

ArrayList list = GetAllActiveDirectoryUsersByDisplayName("company.com");

                foreach (string x in list)
                {
                  Console.WriteLine(x);
                }
于 2013-01-11T09:34:44.627 に答える