Question

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();
Was it helpful?

Solution

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.

OTHER TIPS

I've done a simple search on google and found a lot of information on this. I think you are in the good direction, maybe compare your code with these links:

How to get list of Organizational Unit in Active Directory or here on stack overflow

This is what worked for me

IEnumerable<string> machineOU;
using (var context = new PrincipalContext(ContextType.Domain))
using (var comp = ComputerPrincipal.FindByIdentity(context, Environment.MachineName))
{
  machineOU = comp.DistinguishedName.Split(',').Where(s => s.StartsWith("OU="));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top