views:

1232

answers:

6

I'm trying to figure out how to search AD from C# similarly to how "Find Users, Contacts, and Groups" works in the Active Directory Users and Computers tool. I have a string that either contains a group name, or a user's name (usually in the format firstname middleinitial [if they have one] lastname, but not always). Even if I do a seperate query for groups vs. users, I can't come up with a way to search that captures most user accounts. The Find Users, Contacts, and Groups tool brings them back almost every time. Anyone have any suggestions?

I already know how to use the DirectorySearcher class, the issue is that I can't find a query that does what I'd like. Neither cn nor samaccount name has anything to do with the user's name in this, so I'm unable to search on those. Splitting things up and searching on sn and givenName doesn't catch anywhere near as much as that tool does.

+4  A: 

System.DirectoryServices has two namespaces...DirectoryEntry and DirectorySearcher.

More info on the DirectorySearcher here:

http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx

You can then use the Filter property to filter by Group, user etc...

So if you wanted to filter by account name you would set the .Filter to:

"(&(sAMAccountName=bsmith))"

and run the FilterAll method. This will return a SearchResultCollection that you can loop through and pull information about the user.

Miyagi Coder
Thanks, though I know about DirectorySearcher. The issue is that I can't come up with a query to find the users in AD.
Sunookitsune
@Sunookitsune - So you are trying to replicate the exact functionality "Find Users, Contacts, and Groups"?
Miyagi Coder
@Miyagi Coder I wouldn't say exactly that functionality, but at least get something near how it searches for users. Or find something else that will work, because I'm stumped.
Sunookitsune
+2  A: 

You need to build the search string based on how you're looking for the user.

using (var adFolderObject = new DirectoryEntry())
{
     using(var adSearcherObject = new DirectorySearcher(adFolderObject))
     {
          adSearcherObject.SearchScope = SearchScope.Subtree;
          adSearcherObject.Filter = "(&(objectClass=person)(" + userType + "=" + userName + "))";

          return adSearcherObject.FindOne();
     }
}

userType should either be sAMAccountName or CN depending on how the username is formatted.

ex:
firstname.lastname (or flastname) will usually be the sAMAccountName
FirstName LastName will usually be the CN

Slipfish
+2  A: 

To add onto Miyagi's answer....

Here's a filter/query to apply to DirectorySearcher

DirectorySearcher ds = new DirectorySearcher();

ds.Filter = "samaccountname=" + userName;

SearchResult result = ds.FindOne();
curtisk
Bonzai Curtis!!!!
Miyagi Coder
+2  A: 
public DirectoryEntry Search(string searchTerm, string propertyName)
{
   DirectoryEntry directoryObject = new DirectoryEntry(<pathToAD>);

   foreach (DirectoryEntry user in directoryObject.Children)
   {
      if (user.Properties[propertyName].Value != null)    
         if (user.Properties[propertyName].Value.ToString() == searchTerm)
             return user;                       
   }

   return null;
}
Scott Lance
+6  A: 

Are you on .NET 3.5 ? If so - AD has great new features in .NET 3.5 - check out this article Managing Directory Security Principals in .NET 3.5 by Ethan Wilanski and Joe Kaplan.

One of the big new features is a "PrincipalSearcher" class which should greatly simplify finding users and/or groups in AD.

If you cannot use .NET 3.5, one thing that might make your life easier is called "Ambiguous Name Resolution", and it's a little known special search filter that will search in just about any name-related attribute all at once.

Specify your LDAP search query like this:

searcher.Filter = string.Format("(&(objectCategory=person)(anr={0}))", yourSearchTerm)

Also, I would recommend filtering on the "objectCategory" attribute, since that's single-valued and indexed by default in AD, which is a lot faster than using "objectClass".

Marc

marc_s
That's exactly what I was looking for! Thanks a lot!
Sunookitsune
A: 

Got this from the Joe Kaplan and Ethan Wilansky Article Use this Using (from referencing the System.DirectoryServices.AccountManagement dll):

using System.DirectoryServices.AccountManagement;

private bool CheckUserinAD(string domain, string username)
{
    PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, domain);
    UserPrincipal user = new UserPrincipal(domainContext);
    user.Name = username;
    PrincipalSearcher pS = new PrincipalSearcher();
    pS.QueryFilter = user;
    PrincipalSearchResult<Principal> results = pS.FindAll();
    if (results != null && results.Count() > 0)
        return true;
    return false;
}
Gabriel Guimarães