Fine-tune Your Active Directory Operations with .NET

Fine-tune Your Active Directory Operations with .NET

he .NET framework provides strong support for accessing Active Directory Services, letting you create, edit, delete, and search for directory objects efficiently. This article discusses the benefits of Active Directory Services, its specific features, and how to manipulate Active Directory objects using .NET code.

To implement the techniques discussed in the article, the minimum requirements are:

  • .NET framework: version 1.1 or higher
  • Operating System: Windows XP/2000 or higher

I won’t discuss how to install and configure Active Directory in this article, but here are links to installation instructions for Windows 2000 Server and Windows 2003 Server.

For Windows 2000, you can migrate existing groups, users, and computers to Active Directory using the downloadable Windows 2000 Active Directory Migration Tool.

Directory Services and Active Directory
A directory service is a centralized repository of network information used to store and manage complex hierarchical data, authorization, and user management. Directory services provide ways to define new object types and specify the attributes for those types, letting developers create instances of these types and store them in the repository.

Typically, developers gain access to the repository using an API. The basic difference between a directory service and a Relational Database Management System (RDBMS) is that while the former manages access to hierarchical structure of objects, the later manages access to relational tabular data. Unfortunately, there’s a drawback: Reading and writing data to a directory service is far slower than similar operations against an RDBMS. Further, unlike RDBMSs, Active Directory doesn’t have any support for transactions.

Microsoft’s Active Directory is an implementation of a directory service. It is a distributed, replicated, and hierarchical Windows service that’s well-integrated with the host OS. Another way to think of it is as an object-oriented hierarchical database that represents network resources in the system. Active Directory provides an API to locate and manage these resources, making them available to authorized users and groups.

Active Directory is a central and secure repository of an organization’s data designed for use in distributed computing environments. It provides policy-based administration. Active Directory, originally named “NT Directory Service,” was introduced with Windows 2000, and is basically Microsoft’s implementation of an LDAP directory service for Windows OSs.

Active Directory Features
The basic features of Active Directory are:

  • Security
  • Scalability
  • Hierarchical object grouping
  • Support for open standards
  • Extensibility
  • Backward compatibility with earlier Windows OSs

The objects Active Directory contains typically fall into one of the following categories:

  • Resources?Printers, scanners, user details, etc.
  • Services?for example, DirectoryService, SecurityService, etc.
  • Users?user credentials

What are Active Directory Objects?
Each object in Active Directory is an instance of a class defined in a schema. The objects in the Active Directory are strongly typed and are organized in a tree-like structure where the root object represents the domain, and the other nodes represent containers that can hold one or more objects. The schema is responsible for defining the types and the attributes of the objects in the repository.

Typical objects in an Active Directory represent files, printers, users, or software. Each object has its own attributes and an Access Control List (ACL). Active Directory identifies objects using a distinguished name that specifies the domain where the object is located and the path of the object. Distinguished names have several components, called the CN, OU and DC. The CN represents the common name of the object in the Active Directory, OU represents the organizational unit to which the object belongs, and DC is the domain controller or the DNS name of the object.

Active Directory Protocols
Active Directory can use either of two protocols:

  • Lightweight Directory Access Protocol (LDAP)
  • Active Directory Service Interface (ADSI)

LDAP is a generalized protocol for accessing information directories. It is a light-weight, open-source, cross-platform, client-server protocol for accessing a directory service over a network. You can use LDAP to access LDAP-compliant directories from virtually any platform.

In contrast, ADSI is a COM-based programmatic interface specific to Microsoft that abstracts directory-service protocols from various vendors into a common API. The .NET framework includes the System.DirectoryServices namespace, which contains a set of classes that use ADSI to interact with a variety of network providers.

You can download the Active Directory Service Interfaces (ADSI), Version 2.5 if they aren’t available on your system.

Programming Active Directory with .NET
To program Active Directory with .NET, you first need to include the System.DirectoryServices.dll file in your project, and include the System.DirectoryServices namespace in your source file(s). The System.DirectoryServices namespace provides managed-code access to Active Directory by wrapping up the ADSI providers. The classes contained in this namespace include:

  • DirectoryEntry
  • PropertyCollection
  • PropertyValueCollection
  • DirectoryEntries
  • DirectorySearcher
  • SearchResultCollection
  • SearchResult

Of these classes, you’ll use the DirectoryEntry class, the DirectoryEntries collection, and the DirectorySearcher classes most frequently. The DirectoryEntry class works with the objects in Active Directory?you use it to create, edit, and delete objects from the repository. The DirectoryEntries class represents a collection of DirectoryEntry instances. You use the DirectorySearcher class (as the name implies) to search objects in the ActiveDirectory using LDAP.

ADSI in turn uses LDAP to communicate to Active Directory. LDAP is preferred for accessing relatively static data from multiple locations irrespective of their platforms, and LDAP is the only system-supplied ADSI provider that supports directory searching.

The DirectorySearcher class supports complex searches, including filters. Note, however, that you can use DirectorySearcher only with the LDAP provider and not other with providers such as Novell NetWare Directory Services (NDS) or the Microsoft Internet Information Services (IIS) provider.

Connecting to Active Directory
To connect to Active Directory you bind to it using a binding string, specifying the binding path. The components of this binding string are:

  • Protocol
  • Server Name
  • Port Number
  • Distinguished Name
  • User Name
  • Password
  • Authentication Type

For example, here’s a typical binding string:


In the preceding binding string, the protocol is LDAP://, the server name is the IP address, CN implies the common name (which defines an object within the directory), OU stands for Organizational Unit, and DC stands for Domain Controller.

The following code example demonstrates how to use a binding string to connect to Active Directory.

   DirectoryEntry directoryEntry = new DirectoryEntry(      "LDAP://;DC=DomainName");   

Adding Objects to Active Directory
Active Directory is organized hierarchically using objects that can be categorized into one of the following categories:

  • Resources (Example: Printers, Scanners, etc)
  • Services (Example: E-Mail)
  • Users (Example: Users and Groups)

The following code snippet demonstrates adding a new “user” object to Active Directory.

   DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" +       Environment.MachineName + ",computer");   DirectoryEntry de = directoryEntry.Children.Add("Joydip", "user");   de.Invoke("SetPassword", new object[] { "jk" });   de.Invoke("Put", new object[] { "Description", "New User" });   de.CommitChanges();   DirectoryEntry dE = directoryEntry.Children.Find(      "Guests", "group");   if (dE != null)    {      dE.Invoke("Add", new object[]       {         de.Path.ToString() });      }   }

Searching Active Directory
The most common use of a directory is to locate resources?in other words, perform a search. The following code snippet demonstrates how to search for an object within Active Directory.

   DirectoryEntry directoryEntry= new DirectoryEntry(      "LDAP://;DC=DomainName");   DirectorySearcher directorySearcher = new       DirectorySearcher(directoryEntry);   directorySearcher.Filter = ("Some Filter");   foreach(SearchResult searchResult in directorySearcher.FindAll())    {      Console.WriteLine(searchResult.GetDirec      toryEntry().Path);   }

Modifying Objects in Active Directory
You can update objects in the repository as shown below:

   DirectoryEntry directoryEntry= new DirectoryEntry(      "LDAP://;DC=DomainName");   if(de.Properties.Contains("city"))   {      de.Properties["city"][0] = "Hyderabad";      de.CommitChanges();   }

Deleting an object in the Active Directory
The following code snippet shows how we can delete an object in the Active Directory.

   DirectoryEntry directoryEntry = new DirectoryEntry(      strPath,strUserName, strPassword);   DirectoryEntry user = directoryEntry.Children.Find(      "CN=UserName", "User");     directoryEntry.Children.Remove(user);    directoryEntry.CommitChanges();     directoryEntry.Close();

Using Active Directory in C#
This section discusses the implementation of a simple Windows application that displays the names of all the groups from the Active Directory. It also displays the list of all the users of a particular group in the Active Directory. Figure 1 shows a screen shot of the application at runtime.

Figure 1. Sample Application: This application retrieves a list of all users in a selected group from Active Directory.

You can download the source code for this sample application to follow along or try it yourself. The two important files in the downloadable source the Windows Form Form1.cs, and a C# file, ADUtilities.cs, which defines a class containing methods to query Active Directory and return results. Here’s the code for the ADUtilities class:

   public class ADUtilities   {      Private DirectoryEntry activeDirectory = null;         public ADUtilities()      {         activeDirectory = new             System.DirectoryServices.DirectoryEntry(            "WinNT://"+Environment.MachineName+",computer");      }         public DirectoryEntry IsValidUser(string userName)      {         return activeDirectory.Children.Find(userName, "User");      }         public string GetUserDomain(string userName)      {         DirectoryEntry user = IsValidUser(userName);         if(user != null)             return user.Path;         return null;      }         public ArrayList GetGroupNames()       {         ArrayList groupNames = new ArrayList();         foreach (DirectoryEntry directoryEntry in             activeDirectory.Children)          {            if (directoryEntry.SchemaClassName.Equals("Group"))                groupNames.Add(directoryEntry);         }         return groupNames;       }         public ArrayList GetUsersInGroup(DirectoryEntry group)       {         ArrayList groupUsers = new ArrayList();         foreach (DirectoryEntry directoryEntry in group.Children)          {            if (directoryEntry.SchemaClassName.Equals("User"))                groupUsers.Add(directoryEntry);         }         return groupUsers;       }   }

The ADUtilities class constructor connects to Active Directory by instantiating a DirectoryEntry class instance, which it then uses in the various methods to retrieve the group names (GetGroupNames) and a list of all the users in a particular group (GetUsersInGroup) in the Active Directory. Note that the Path property of the DirectoryEntry class returns the domain name to which a user belongs.

The simplicity with which you can use .NET code and ADSI to access, update, and search Active Directory (and other directory stores as well) adds to the attractiveness of using directory services within organizations that use .NET. In short, Active Directory is a centralized, secure repository of organizational resources and security information, that’s easily accessible via .NET code, which can greatly simplify enterprise-level resource management.


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist