Querying Active Directory

In this post, we show how to query Active Directory using out of box tools as well as custom code. 

Since joining Premier Field Engineering, I realized that an essential part of understanding SharePoint requires an understanding of Active Directory and LDAP.  You need to have a decent grasp on the basics of LDAP to effectively configure and troubleshoot problems with user profile imports.  I’ll admit, this is an area that I used to be very weak in, but it is not at all difficult to ramp up and become proficient.

Querying Using Active Directory Tools

I set up a domain called SharePoint.com and added an Organizational Unit (OU) called “Contractors”, then added a few users using the “Active Directory Users and Computers” MMC snap-in on the domain controller.

image

Besides the MMC tools, other tools are installed when you create a domain controller.  Open the tool LDP.exe on the domain controller.  In the Connection menu, choose “Connect” and leave the Server string empty, indicating you want to connect to the local directory.

image

Next, in the Connection menu, choose Bind and bind as the currently logged in user.

image

On the View menu, choose Tree, and navigate to an individual user.  This is an incredibly useful tool to see the properties for a user and their values:

image

Note: You can install LDP to another server, such as a SharePoint web front end, by adding the Active Directory Lightweight Directory Services role to a Windows Server 2008 instance. This can be useful in troubleshooting connectivity from a SharePoint web front end to the domain controller, allowing you to query the DC from the web front end as the same user account that is running user profile imports.

In the screen shot above, notice the property “cn” with value “Andrew Fuller”, and the “userPrincipalName” property with value “andrewfuller@SharePoint.Com".  We are going to show how to query these same properties using C#.

Querying Using C#

To get started, add a reference in your project to System.DirectoryServices. 

image

The code to connect to Active Directory is very simple.  We start by creating a new instance of the DirectoryEntry class.  Think of the Active Directory domain as a tree, the DirectoryEntry class lets us point to a specific node in the tree.  Referring to the screen shots above, we want to point to the Contractors node. 

 DirectoryEntry entry = new DirectoryEntry("LDAP://OU=Contractors,DC=SharePoint,DC=Com");

Just like with SQL queries, we need to tell the query engine what properties we want to include in the results. We do this by using the PropertiesToLoad.Add method. Also, just like SQL queries provide a WHERE clause to filter results, we can filter results in Active Directory to only include users with the Filter property.

 ds.PropertiesToLoad.Add("name");                
ds.PropertiesToLoad.Add("userPrincipalName");

ds.Filter = "(&(objectClass=user))";

Now that we have told the query engine where we want to connect, what we want in the results, and how we want to filter results, we execute the query using the FindAll method.

 SearchResultCollection results = ds.FindAll();

The results are returned in a SearchResultCollection, each SearchResult object contains a hashtable of properties and values.  Think of each SearchResult as a single user.  The properties are the same properties that we included in the query.  Each property can have multiple values, but our results contain just a single value that we access through the 0 index:

 foreach (SearchResult result in results)
{
    Console.WriteLine("{0} - {1}", 
        result.Properties["name"][0].ToString(),
        result.Properties["userPrincipalName"][0].ToString());
}

Part of the reason this is so cool is because it becomes incredibly handy to troubleshoot problems connecting to Active Directory and querying.  Knowing what is happening under the hood and how to use tools like LDP become invaluable tools in your toolbelt, especially for SharePoint developers doing things with user profiles.

The Full Code Listing

 using System;
using System.DirectoryServices;

namespace SharePointConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://OU=Contractors,DC=SharePoint,DC=Com");

            using (DirectorySearcher ds = new DirectorySearcher(entry))
            {
                ds.PropertiesToLoad.Add("name");
                ds.PropertiesToLoad.Add("userPrincipalName");

                ds.Filter = "(&(objectClass=user))";

                SearchResultCollection results = ds.FindAll();

                foreach (SearchResult result in results)
                {
                    Console.WriteLine("{0} - {1}",
                        result.Properties["name"][0].ToString(),
                        result.Properties["userPrincipalName"][0].ToString());
                }
            }
        }                
    }
}

 

The results:

Andrew Fuller - andrewfuller@SharePoint.Com

Nancy Davolio - NancyDavolio@SharePoint.Com

Janet Leverling - JanetLeverling@SharePoint.Com

Margaret Peacock - MargaretPeacock@SharePoint.Com

 

For More Information

Howto: (Almost) Everything In Active Directory via C#

Introduction to System.DirectoryServices, Part 2

Getting Search Results

Using ADSI, LDAP, and Network Management Functions With Active Directory