我如何通过 C# 以编程方式获取 Active Directory 林的根

How can i programmatically get the root of an Active Directory Forest via C#

我的客户有一个巨大的 Active Directory 林。例如:

根目录

company.com
  de.company.com
  us.company.com
  in.company.com
  xx.company.com

当我得到当前用户时,我得到 domainname\username。当我获取域名并想在这个域中搜索世界上的其他用户时,我不能因为我需要知道 company.com 才能进行目录搜索。

在 C# 中有没有办法获取我使用 DirectorySearcher 或任何其他 C# 方法查询 AD 的根对象?

要获取用户的根对象,请使用 属性 或属性 distinguished name 来确定 Active Direcotry 中的完全限定路径。从右边读取结构并提取根元素。

E. G。 cn=John Doe, ou=People, dc=sun.com

可以从 RootDSE 分区获取根目录林名称。查看 rootDomainNamingContext 属性。这将 return 您的林根域。我不建议从用户 DN 中提取林名称,因为如果您在一个林中有 2 个域树,它就不起作用。第二个选项是在当前域的全局目录中搜索用户。全局目录包含整个林中所有用户的部分副本

下面的代码对全局目录执行搜索。我有 2 个域,在我的林中,所以 return 我有 2 个用户。请注意,您将不得不处理多个结果 returned:

        var forest = Forest.GetCurrentForest();
        var globalCatalog = GlobalCatalog.FindOne(new DirectoryContext(DirectoryContextType.Forest, forest.Name));

        using (var connection = new LdapConnection(new LdapDirectoryIdentifier(globalCatalog.Name, 3268)))
        {
            var entries = new List<SearchResultEntry>();

            var searchRequest = new SearchRequest(string.Empty, "(samaccountname=administrator)", SearchScope.Subtree, null);
            var searchOptionsControl = new SearchOptionsControl(System.DirectoryServices.Protocols.SearchOption.DomainScope);

            searchRequest.Controls.Add(searchOptionsControl);

            var pageResultRequestControl = new PageResultRequestControl(1000);

            searchRequest.Controls.Add(pageResultRequestControl);

            do
            {
                var response = (SearchResponse)connection.SendRequest(searchRequest);

                if (response != null)
                {
                    if (response.ResultCode != ResultCode.Success)
                    {
                        throw new ActiveDirectoryOperationException(response.ErrorMessage, (int) response.ResultCode);
                    }

                    foreach (var c in response.Controls.OfType<PageResultResponseControl>())
                    {
                        pageResultRequestControl.Cookie = c.Cookie;
                        break;
                    }

                    entries.AddRange(response.Entries.Cast<SearchResultEntry>());
                }
            }
            while (pageResultRequestControl.Cookie != null && pageResultRequestControl.Cookie.Length > 0);
        }

关于这段代码的几点说明: 1.当然这段代码不是生产代码。你可以写更通用的LdapSearcher,比如一个可以查到here。如果需要,您可以制作此搜索器的同步版本。 2. 我强烈建议在基于服务的应用程序中使用 LdapConnection 而不是 DirectorySearcher,因为在企业环境中使用 DirectorySearcher 会导致内存泄漏和其他 issues