Microsoft.NET

……………………………………………….Expertise in .NET Technologies

Access Active Directory data via .NET

Posted by Ravi Varma Thumati on October 6, 2009

Directory is the centerpiece of a Windows Server-based network. The .NET Framework makes it easy to access data contained in the directory, thus providing another data source for developers. Discover how you can access data in the directory, as well as store new data in it.

If you’re working within a Windows Server-based network, you are probably using Microsoft’s Active Directory. Active Directory’s purpose is to reduce the number of directories and namespaces within a network and provide a unified view of a complex network.

You will invariably need to access the directory when developing applications within this environment. We examine a few ways to interface with an Active Directory, and describe how you can manipulate its data.

Active Directory primer

Before diving into .NET integration, let’s start off with a review of Active Directory terminology.

Microsoft used the X.500 directory services model as a blueprint for Active Directory. The X.500 standard logically divides a directory service structure into a servername.subdomainname.domainname.com layout. In X.500, directory information is stored across the hierarchical layout in what is called Directory System Agent. Microsoft designed Active Directory around many of the basic principles of the X.500 definition, but it is not compatible with X.500 implementations.

Every object in the Active Directory has a distinguished name, which identifies the domain where the object is located and the path by which the object is reached. A typical distinguished name in Active Directory is:

CN=Tony Patton,OU=Contributors,DC=TechRepublic

The components of this distinguished name include:

  • CN: The common name, which defines an object within the directory. In this case, the common name is Tony Patton.
  • OU: The organizational unit to which the object belongs.
  • DC: The domain of the object. It is the DNS name for the Active Directory domain, which is TechRepublic in our example.

As the breakdown of the distinguished name demonstrates, an Active Directory system is arranged in a hierarchical tree. Each node on the tree represents a resource or service available on the network. In the previous example, the top node is TechRepublic; it contains the Contributors OU, which can include one or more objects (it includes the Tony Patton object). The complete path to the object is unique within the directory tree.

Each node of the directory tree contains a set of properties that can be retrieved and manipulated. The following terms are useful when working with Active Directory.

  • Directory Service: An information source used to store information.
  • Active Directory Schema: Defines attributes for directory objects. It is analogous to a database schema that defines a database structure.

Let’s turn our attention to programmatically working with an Active Directory.

Directory access via code

The .NET Framework provides the System.DirectoryServices namespace for Active Directory access. It utilizes Active Directory Services Interfaces (ADSI) technology that Microsoft provides for working with a variety of network providers. The namespace contains two component classes:

  • DirectoryEntry: Used to work with individual nodes or objects in the Active Directory hierarchy. You use it along with helper classes to manipulate directory resources and navigate the directory tree. You can create, delete, rename, move a child node, and enumerate children.
  • DirectorySearcher: Allows you to perform directory queries using Lightweight Directory Access Protocol (LDAP), which is the only ADSI provider that supports directory searching. You can use the DirectoryEntry class to work with the search results.

While this isn’t an exhaustive list of the classes contained in the namespace, it is the two most important and most-often used. The C# code below accesses the Active Directory on my network.

C#:
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://192.168.1.1/CN=Users;DC=DomainName";
de.Username = @"DomainName\UserName";
de.Password = "Password";
VB.NET
Dim de As DirectoryEntry
Set de = New DirectoryEntry()
de.Path = "LDAP://192.168.1.1/CN=Users;DC=DomainName"
de.Username = @"DomainName\UserName"
de.Password = "Password"

This gives you access to the Active Directory, so you can work with directory objects. You may notice the path uses LDAP. ADSI includes four directory service providers as listed below (I also offer the syntax for each):

  • Windows 2000 or Windows XP: WinNT://path
  • LDAP: LDAP://path
  • Novell NetWare Directory Service: NDS://path
  • Novell NetWare 3.x: NWCOMPAT://path

Note: Working with Active Directory does require the ADSI SDK or ADSI runtime to be installed to create applications that utilize the functionality. It is installed by default with Windows 2000 and XP. We can extend the sample code to access all properties of the object, as you can see as below.

C#
DirectoryEntry de = new DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName");
foreach(string key in de.Properties.PropertyNames)
{
               Console.WriteLine(key + " = ");
               foreach(Object obj in de.Properties[key])
               Console.WriteLine(obj);
}
VB.NET
Dim de As DirectoryEntry = New DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName")
Dim key As String
Dim obj As Object
For Each Key In de.Properties.PropertyNames
               Console.WriteLine(key & " = ")
               For Each obj In de.Properties(key)
                              Console.WriteLine(CStr(obj))
               Next obj
Next Key

With access to the directory, we may locate and manipulate existing entries, as well as add new objects.

Changing object properties

When working with a directory, you may need to alter one or more properties of an object. For instance, a user’s telephone number stored in the directory may change. The code below uses the aforementioned classes to change this property. The CommitChanges method must be called to make the changes permanent. If you do not use this method, the changes are not saved.

C#
DirectoryEntry de = new 

DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName");
de.Properties["HomeNumber"])[0] = "111-999-9999";
VB.NET
de.CommitChanges();
Dim de As DirectoryEntry = New
DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName")
objDirEnt.Properties("HomeNumber")(0) = "111-999-9999"

You can use this approach with all properties. You may encounter a situation where a new object needs to be added to the directory.

Adding a new object

It’s simple to add a new object. You begin with a DirectoryEntry object and use the Add method of its Children property to add a new object. It uses the hierarchical structure of the directory, so you are adding nodes to the entry. The C# code below adds a new directory entry (a user).

C#
DirectoryEntry de = new
DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName");
de.Children.Add("Joe Blow", "user");
de.CommitChanges();
VB.NET
Dim de As DirectoryEntry = New
DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName")
de.Children.Add("Joe Blow", "user")
de.CommitChanges()

This is a very basic example since more user information would surely be added. You may also need to ensure the user doesn’t exist before adding it.

Searching the directory

The DirectorySearcher class makes it easy to search for existing objects in the directory. The C# code below conducts a search and displays the results. The code creates an instance of the DirectorySearcher class using the existing DirectoryEntry object. The Filter property of the DirectorySearcher class defines the search criteria. The FindAll method returns all objects meeting the search criteria, and a loop is used to display the path to the matching entries.

C#
DirectoryEntry de= new
DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName");
DirectorySearcher srch = new DirectorySearcher(de);
srch.Filter = ("(HomeNumber=999-000-0000)");
foreach(SearchResult se in srch.FindAll())
{
               Console.WriteLine( se.GetDirectoryEntry().Path );
}
VB.NET
Dim de As New DirectoryEntry("LDAP://192.168.1.1/CN=Users;DC=DomainName")
Dim srch As New DirectorySearcher(de)
Dim re As SearchResult
srch.Filter = ("(HomeNumber=999-000-0000)")
For Each re In srch.FindAll()
               Console.WriteLine(re.GetDirectoryEntry().Path)
Next re

Another data source

Active Directory provides a hierarchical data structure for network data. In addition, the DirectoryEntry and DirectorySearcher classes provide easy access to the contents of the directory via a developer’s favorite language. You can access data in the directory as well as store new data in it. This is another data storage area at your fingertips.

Advertisements

One Response to “Access Active Directory data via .NET”

  1. I haven’t checked in here for some time as I thought it was getting boring, but the last several posts are good quality so I guess I will add you back to my everyday bloglist. You deserve it friend 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: