MANY corporate environments rely on a backbone system that controls access to the entire corporate network. One of the more common systems out there is Microsoft’s Active Directory. Active Directory is a directory service. It is a hierarchical system of objects where each object can be a phyical or virtual entity within the corporate environment.  Entities can range from being a meeting room, a person, a printer, or a computer system.

These entities can then be grouped together to form organisational units. Organisational Units are created to tie common entities together; whether it be a geographical grouping or a structure grouping. Each entity is comprised of many attributes. These attributes provide additional information about the entity. For example a Person entity will have their Login, Firstname, Surname and Department etc as attributes.

Developing a software solution for a corporate environment will most likely entail Active Directory access for various reason. In this article I will explain how you can create your own Active Directory querying utility to suit your requirements…

System.DirectoryServices Namespace

The first thing you’d want to do is include a reference to the System.DirectoryServices namespace. This is the system library that contains all the objects needed to query your Active Directory service.

Making the connection

Once that is done; its time to connect to your Directory Service using LDAP.
LDAP stands for Lightweight Directory Access Protocol. It is one of many access protocols available to communicate with Acitve Directory.

Knowledge of the following .Net classes will be helpful in understanding how communication between your .Net application and the Active Directory service is achieved:

  • DirectoryEntry – The main connection to your Active Directory server
  • DirectorySearcher – The object passed into our LDAP query to filter for the required entity objects
  • SearchResultCollection – A collection that stores multiple AD entities if more than one is found
  • SearchResult – A single AD entity with its corresponding attributes

First up, create a connection to your Active Directory service. The ADServer should be something similar to “LDAP://my-server.com.au/dc=com,dc=au“.

            DirectoryEntry directoryEntry = new DirectoryEntry(this.ADServer.Text
                                                            , this.ADUsername.Text
                                                            , this.ADPassword.Text);

Create a new DirectorySearcher object to query the AD server with. For now, just a new object is sufficient. Later on in this article I will explain how to select which attributes to obtain from the AD server. Without explicitly listing your attributes the DirectorySearcher will simply return all attributes for all entities matching your filter criteria.

DirectorySearcher searcher = new DirectorySearcher(directoryEntry);


Filtering the data

The next step is to write our filter criteria for our query. This is simply the DirectorySearcher.Filter property of your DirectorySearcher object. The filter you will use is going to tell the AD Server to only query the “user” entities, that lie within the “person” category, where the sAMAccountName attribute equals to our input value. We also specify AD to search all sub-trees of the hierarchical structure.

            searcher.Filter = "(&(objectClass=user)(objectCategory=person)(samaccountname=" + this.UsernameTextBox.Text + "))";
            searcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;

That’s pretty much it!! The final is step is to execute the search..

Searching

Below is a snippet of the code that traverses all the entities in the ResultCollection. Spitting out all the attributes in the Entity object to a local String variable. Then displaying the output as textbox text.

            SearchResultCollection resultCollection = searcher.FindAll();

            foreach (SearchResult result in resultCollection)
            {
                string str = "";
                foreach (string propertyName in result.Properties.PropertyNames)
                {
                    try
                    {
                        str += propertyName + ":" + (string)(result.Properties[propertyName][0]) + System.Environment.NewLine;
                    }
                    catch
                    {
                    }

                }

                this.OutputTextBox.Text += str;
            }

To access a specific attribute from an entity; refer to the ‘Properties‘ property object, which is an array of values indexed by the attribute name. The value of the attribute is the first item in the array returned.

I have listed some examples below:

result.Properties["GivenName"][0]
result.Properties["Sn"][0]
result.Properties["Mail"][0]

Try out the code above. You may notice that it takes a few seconds to return just one entity. That is because in our DirectorySearcher object we didn’t limit the data we really wanted. So our query returned all AD attributes for us. You will most certainly only want to grab the data that is necessary for your situation. This will dramatically increase its performance.

The above code is useful if you want to check out all the available attributes within Active Directory.

Filtering the attributes

Let’s say we are only interested in the two attributes: sAMAccountName and Mail
Before we execute our query with the AD Server, we can optimise the search to only return these two attributes with the following lines of code:

            DirectorySearcher searcher = new DirectorySearcher(directoryEntry);
            searcher.PropertiesToLoad.Add("sAMAccountname");
            searcher.PropertiesToLoad.Add("Mail);

            searcher.Filter = "(&(objectClass=user)(objectCategory=person)(samaccountname=" + this.UsernameTextBox.Text + "))";
            searcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;

With this new code, our Output string will only contain the two attributes we requested for.
Also take note of the time the query takes – it should be alot quicker than before!