STORM STORM - 24 days ago 7
C# Question

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

My customer has a huge Active Directory forerst. For example:

Root

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


When i get the current user i get
domainname\username
. When i grab domainname and want to search in this domain for other users in the world, i can't cause i need to know company.com to do a directory search.

Is there a way in C# to get the root object which i use with the DirectorySearcher or any other C# method to query the AD?

Answer

root forest name can be ontained from RootDSE partition. Look at rootDomainNamingContext attribute. This wiil return you forest root domain. I do not recommend to extract forest name from user DN, as it will not work in case if you have 2 domain trees in one forest. The second option is to search users in global catalog of current domain. Global catalog contains partial replica of all users from the entire forest

The code below performs the search over the global catalog. I have 2 domains, in my forest so it returns me 2 users. Be aware, that you will have to deal multiple results 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);
        }