Wednesday, October 19, 2005

What attributes are available on my Active Directory Object?

The question arises occasionally on how to dynamically determine what attributes are available for a given object in Active Directory (typically the user object).  This is a different question than what attributes are actually populated with a value on an instance of the object.  We can find what attributes are defined for an object by naturally looking into the schema for the object.  This can be by inspecting the schema partition and searching for the class, or by taking an instance of the object and accessing the schema.

I will present the latter method in which we have an instance of an object and we wish to determine the available attributes (again, not necessarily populated).

using System;
using System.DirectoryServices;
using System.Reflection;
 
 
DirectoryEntry searchRoot = new DirectoryEntry(
    adsPath,
    null,
    null,
    AuthenticationTypes.Secure
    );
 
using (searchRoot)
{
    DirectorySearcher ds = new DirectorySearcher(
        searchRoot,
        "(sAMAccountName=Ryan_Dunn)"
        );
 
    ds.SizeLimit = 1;
 
    SearchResult sr = null;
 
    using (SearchResultCollection src = ds.FindAll())
    {
        if (src.Count > 0)
            sr = src[0];
    }
 
    if (sr != null)
    {
        using (DirectoryEntry user = sr.GetDirectoryEntry())
        using (DirectoryEntry schema = user.SchemaEntry)
        {
            Type t = schema.NativeObject.GetType();
 
            object optional = t.InvokeMember(
                "OptionalProperties",
                BindingFlags.Public | BindingFlags.GetProperty,
                null,
                schema.NativeObject,
                null
                );
 
            if (optional is ICollection)
            {
                foreach (string s in ((ICollection) optional))
                {
                    WL("Optional: {0}", s);
                }
            }
 
            object mand = t.InvokeMember(
                "MandatoryProperties",
                BindingFlags.Public | BindingFlags.GetProperty,
                null,
                schema.NativeObject,
                null
                );
 
            if (mand is ICollection)
            {
                foreach (string s in ((ICollection) mand))
                {
                    WL("Mandatory: {0}", s);
                }
            }
        }
    }
}

This code will take the user object I find and then iterate through all the attributes defined for this object type (in this case the user object).