views:

827

answers:

2

I have a function that retrieves the fullname of a user based on user name and domain. This function runs in ASP.NET thread under an impersonated user. When I use Directory searcher on a remote AD branch, I believe I'm getting the SID number instead of the property (cannot verify it occurs on a different box).

public string GetUserFullName(string userName, string domainName)
{  
    DirectoryEntry rootEntry = new DirectoryEntry("GC://dc=company,dc=net");
    string filter = string.Format("(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(userPrincipalName={0}@{1}.company.net))", userName, domainName);
    DirectorySearcher searcher = new DirectorySearcher(rootEntry, filter, new string[] { "displayName" });
    rootEntry.AuthenticationType = AuthenticationTypes.Secure;
    searcher.PageSize = 1000;
    searcher.ServerTimeLimit = new TimeSpan(0, 10, 0);
    searcher.ReferralChasing = ReferralChasingOption.All;
    searcher.Asynchronous = false;

    SearchResult result = searcher.FindOne();
    if (result != null)
    {
        return (string) result.Properties["displayName"][0];
    }
    else
    {
        throw new Exception("Active Directory could not resolve your user name");
    }

}
A: 

I've wrapped up AD into a handy helper library and have always used this method:

    /// <summary>
    /// Returns AD information for a specified userID.
    /// </summary>
    /// <param name="ntID"></param>
    /// <returns></returns>
    public ADUser GetUser(string ntID)
    {          
        DirectorySearcher search = new DirectorySearcher();        

        search.Filter = String.Format("(cn={0})", ntID);

        search.PropertiesToLoad.Add("mail");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("displayName");
        search.PropertiesToLoad.Add("userPrincipalName");
        search.PropertiesToLoad.Add("cn");

        SearchResult result = search.FindOne();

        return new ADUser(result);
    }

ADUser is a custom class that maps a SearchResult to strong typed properties.

I am not sure what your specific problem is, but this has always worked for me.

EDIT: Comparing our code, I see you are not telling search to preload the property...That is probably your problem.

FlySwat
Hi FlySwat, the DirectorySearcher constructor has the properties to load array - in my case { "displayName" }. I'll try using the ADUser class. Thanks,
Adrian Stoica
ADUser is a class I wrote that makes dealing with users a little more sane.
FlySwat
+3  A: 

What version of the .NET framework are you working against? The AD stuff has been revamped quite extensively in .NET 3.5, and offers strongly typed constructs for User and groups and stuff like that now.

Check out the excellent article "Managing Directory Security Principals in the .NET Framework 3.5" by my buddies Joe Kaplan and Ethan Wilansky on MSDN. Excellent stuff indeed.

First of all, you get a class called UserPrincipal which is strongly typed, e.g. all the basic properties are properties on your object. Very helpful indeed.

Secondly, you get a nice "query-by-example" method using PrincipalSearcher - check out this sample from Joe and Ethan's article:

// create a principal object representation to describe
// what will be searched 
UserPrincipal user = new UserPrincipal(adPrincipalContext);

// define the properties of the search (this can use wildcards)
user.Enabled = false;
user.Name = "user*";

// create a principal searcher for running a search operation
PrincipalSearcher pS = new PrincipalSearcher();

// assign the query filter property for the principal object 
// you created
// you can also pass the user principal in the 
// PrincipalSearcher constructor
pS.QueryFilter = user;

// run the query
PrincipalSearchResult<Principal> results = pS.FindAll();

Console.WriteLine("Disabled accounts starting with a name of 'user':");
foreach (Principal result in results)
{
    Console.WriteLine("name: {0}", result.Name);
}

If there's any chance at all, try to get to .NET 3.5 for your AD stuff !

Marc

marc_s
It's NET 2.0. Thanks for pointing this out!!!Adrian
Adrian Stoica