Search code examples
c#active-directorydirectoryservices

Find the domain component from a PrincipalContext


I am trying to find out the domain component via Active Directory Services using a PrincipalContext.

I created the PrincipalContext using very few parameters:

PrincipalContext theContext = new PrincipalContext(ContextType.Domain);

theContext is coming back correctly. I can query many things on it and get expected results. But what I would really like to do is the equivalent of:

Console.WriteLine("Domain Component: " + theContext.Container);

According to MSDN, this only "Gets the value specified in the container parameter in the constructor." Since I've passed in nothing, I'm getting nothing back.

But the theoretical container has the domain components, which are needed for any distinguished names you might need to use or create. I'm specifically looking to create a new user in an organizational unit that I know will be there. But, since I don't know the domain components, I can't create the distinguished name. I haven't seen any support for relative paths.

The best option I've figured is to do a search for any user and then get its distinguished name and chop off the "dc" part.

var searchUser = new UserPrincipal(theContext);
var searcher = new PrincipalSearcher(searchUser);
Principal aUser = searcher.FindOne();
if (aUser != null)
{
    string dn = aUser.DistinguishedName;
    Console.WriteLine(dn.Substring(dn.IndexOf("dc=", StringComparison.InvariantCultureIgnoreCase)));

}

That feels like a poor hack; too much could go wrong. I'm hoping there is something better. Does anyone have an idea?


Solution

  • In order to get the naming context, you should bind to RootDSE. RootDSE provides a lot of useful information of a directory server. Among all of them, defaultNamingContext attribute stores the distinguished name of the domain, which is what you want.

    To bind to the RootDSE of the the domain of the currently logged-on user, you can use serverless binding. To do the serverless binding on RootDSE of the currently logged-on user domain, the binding string should look like this

    LDAP://RootDSE
    

    Here is how you can get it using DirectoryEntry

    DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
    string domainContext = rootDSE.Properties["defaultNamingContext"].Value as string;