How can I find what Organizational Units a computer is part of? ( Active Directory C# )

user1507986 picture user1507986 · Aug 2, 2012 · Viewed 15.9k times · Source

I want to find the most specific OU my computer belongs to in C#. I have code that will get the information I need, but it doesn't feel robust and it would require complicated parsing. Are there better alternatives? Thoughts? Any help is appreciated!

Really what I want is an equivilent to the command prompt command:

dsquery computer -name COMP-HERE

But I need it in C#, which is proving to be problematic.

DirectorySearcher d = new DirectorySearcher("CN=COMP-HERE");
d.PropertiesToLoad.Add("adspath");
SearchResultCollection results = d.FindAll();
foreach (SearchResult searchResult in results) {
    foreach (string propertyKey in searchResult.Properties.PropertyNames) {
        ResultPropertyValueCollection valueCollection = searchResult.Properties[propertyKey];
        foreach (Object propertyValue in valueCollection) {
            Console.WriteLine(
            "{0}:{1}",
            propertyKey,
            propertyValue.ToString());
        }
    }
}
Console.ReadLine();

Answer

Andrew Cooper picture Andrew Cooper · Aug 2, 2012

Here's a solution using PrincipalContext and ComputerPrincipal in the System.DirectoryServices.AccountManagement namespace

string machineOU;
using (var context = new PrincipalContext(ContextType.Domain))
using (var comp = ComputerPrincipal.FindByIdentity(context, Environment.MachineName))
{
    machineOU = String.Join(",", comp.DistinguishedName.Split(',')
                                                       .SkipWhile(s => !s.StartsWith("OU="))
                                                       .ToArray());
}

The Linq treatment of the machine's distinguished name splits it into it's component elements, skips any elements before the first OU=... element, and then recombines the rest., leaving you with the distinguished name of the containing OU.

More Info

The classes in the System.DirectoryServices.AccountManagement namespace provide a fairly high-level abstraction of various type of security principals (accounts).

The PrincipalContext is basically an abstraction of the account repository. It can refer to a machine's account database (PrincipalType.Machine), an Active Directory domain or Global Catalog (PrincipalType.Domain), or an Active Directory Application partition (PrincipalType.ApplicationDirectory).

new PrincipalContext(ContextType.Domain) creates a PrincipalContext representing the local Active Directory domain.

Once we've got this context we can use the FindBy...() static methods on the various principal types (can be UserPrincipal, ComputerPrincipal or GroupPrincipal) to find the AD object we're looking for.