Accessing Directory Services

Mark Strawmyer Presents: .NET Nuts & Bolts


Welcome to the next installment of the .NET Nuts & Bolts column. In this column, we'll explore how to access directory services from within .NET. Specifically, we'll focus on Microsoft's directory service called Active Directory. The topics covered will include how to use the Active Directory for items such as searching and providing authentication services for an application. It will involve using classes in the System.DirectoryServices namespace.

Directory Services

A directory service is a centralized data source that contains information relevant to an organization's computing environment. It provides access to network resource information without the client having to know the specifics of how or where the resource is connected. A directory service is commonly used to store information regarding computers, network devices such as printers, and information on users such as security credentials and application preferences.

Active Directory (AD)

Microsoft Active Directory, originally introduced in Windows 2000, is a directory service introduced by Microsoft to replace the aging Windows NT 4.0 domain architecture. It allows an organization to have a structure that more closely matches the company environment by allowing for a flexible hierarchy, support for a much larger number of network users and resources than what NT could allow, and a whole lot more. It serves as the central security point for controlling access to resources within the network. There are many concepts and designs involved with the AD. For this article, I'm going to assume you are already familiar with the AD object structure. If not, click here to visit Microsoft's site and learn more about the Active Directory.

Active Directory Services Interface (ADSI)

Active Directory Services Interface (ADSI) is a single interface from Microsoft that can be used to administer directory services. It abstracts the capabilities of directory services from different providers so that the same interface can be used regardless of the environment. Directory services that can be accessed through ADSI include, but are not limited to, the following:

  • Novell Netware Directory Service (NDS)
  • Netware 3 bindery
  • Windows NT 4.0 directory
  • Microsoft Active Directory
  • Microsoft directory capable server products: Exchange 5.5 and above, Internet Information Services, Microsoft Commerce Server, and more.

Click here to visit Microsoft's site and learn more about ADSI.

System.DirectoryServices Namespace

The Microsoft .NET Framework includes a System.DirectoryServices namespace contained in the System.DirectoryServices.dll that must be added as a reference in order to use it. It contains the DirectorySearcher and DirectoryEntry classes. These classes utilize the Active Directory Services Interface (ADSI) to interact with and manipulate the directory from within managed code and allow you to access any ADSI provider, including Active Directory.

Each object in a directory service is represented as a DirectoryEntry. It allows you the capability to access information about the directory item such as its name, modify its properties, or even rename or move it to another location in the directory.

The DirectorySearcher is used to execute a query against the directory service. You can search for a single object that matches or multiple matches. It returns a collection of DirectoryEntry objects that are read only.

Connecting to a Directory Service

The first step in doing anything with a directory service, much like a database, is to create a connection it. The act of connecting to a directory service is often referred to as binding. The connection string, known as a path, used to connect to the directory service is dependent upon the provider to which you are connecting. While Windows NT requires that you connect to a specific server, the Active Directory example allows you to bind to the name of the domain instead. A couple of sample paths are listed below.

  • Windows NT 4.0: Connect to the current machine
  • string path = "WinNT://" + Environment.MachineName
                             + ",computer";
  • Active Directory: Connect to a dev.codeguru.com domain
  • string path = "LDAP://CN=Users,DC=dev,DC=codeguru,DC=com";
    or
    string path = "LDAP://dev.codeguru.com";

Once the path statement is worked out for the appropriate provider, all that remains to bind to the directory is to pass it as a parameter to the constructor of a new instance of the DirectoryEntry class.

  • DirectoryEntry entry = new DirectoryEntry(path);

Authenticating

The DirectoryEntry class can be used to authenticate a user login and password against a directory service. Bind to the directory and pass the user login and password of the user you wish to authenticate. You force authentication to occur by retrieving the NativeObject property.

Active Directory Authentication Sample

string path = "LDAP://dev.codeguru.com";
DirectoryEntry entry = new DirectoryEntry( 
path,"dev.codeguru.com\\administrator", "");

try
{ 
// Bind to the native object to force authentication to happen
Object native = entry.NativeObject;
Console.WriteLine("User authenticated!");
}
catch( Exception ex )
{
throw new Exception("User not authenticated: " + ex.Message);
}

Searching the Directory

The DirectorySearcher object has two methods for searching a directory. There is the FindOne method that retrieves the first entry from the directory. There is the FindAll method that retrieves all directory entries that match the search string. By default, the results will load all of the properties for the directory entries that meet the filter criteria. For efficiency, you can restrict the properties loaded by using the PropertiesToLoad collection on the DirectorySearcher.

Active Directory Searching Sample using FindOne

The following sample code uses the FindOne method of the DirectorySearcher class to find the same user we authenticated a moment ago. We will limit the properties that are retrieved during the search.

DirectoryEntry entry = new
                       DirectoryEntry("LDAP://dev.codeguru.com");
try
{
  DirectorySearcher search = new DirectorySearcher(entry);
  search.Filter = "(SAMAccountName=administrator)";
  search.PropertiesToLoad.Add("Name");
  search.PropertiesToLoad.Add("displayName");
  SearchResult result = search.FindOne();
  if( result != null )
  {
    Console.WriteLine("User found");
    foreach( string key in result.Properties.PropertyNames )
    {
      // Each property contains a collection of its own
      // that may contain multiple values
      foreach( Object propValue in  result.Properties[key] )
      {
        Console.WriteLine(key + " = " + propValue);
      }
    }
  }
  else
  {
    Console.WriteLine("User not found");
  }
}
catch( Exception ex )
{
  throw new Exception("User not authenticated: " + ex.Message);
}
Console.ReadLine();

Active Directory Searching Sample using FindAll

The following sample uses the FindAll method of the DirectorySearcher class to retrieve and information on all of the users found in the directory. It then will iterate through the properties for each of the entries found and write them to the console. This time, we will not restrict the properties and will display them all.

DirectoryEntry entry = new
                       DirectoryEntry("LDAP://dev.codeguru.com");
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(objectClass=user)";

foreach(SearchResult result in search.FindAll())
{
DirectoryEntry dirEntry = result.GetDirectoryEntry();
foreach(string key in dirEntry.Properties.PropertyNames) 
{
    // Each property contains a collection of its own
    // that may contain multiple values
    foreach( object propVal in dirEntry.Properties[key] )
    {
      Console.WriteLine(key + " = " + propVal);
    }
  }
  Console.WriteLine("---------------");
}
Console.ReadLine();

Adding a User

Adding a user to the directory is not much more complicated than the searching we were performing before. When binding to the directory, we need to provide user credentials that have the authority to modify a user; otherwise, the update will fail. In addition, make sure that you have all of the attributes required by your AD instance; otherwise, you will get a message similar to "The server is unwilling to process the request" and not be able to add a user. Typically, only the cn (full name) and sAMAccountName are required.

There is an Invoke method that you can use to access properties through native ADSI. All user properties accessible through the DirectoryEntry class can also be set through the Invoke method. However, not all user properties are accessible through the DirectoryEntry class. It is a requirement that the user password is set using the Invoke method because it is not exposed through the DirectoryEntry class. The user must exist in the AD before the password can be set.

If you have more than one Domain Controller, please allow time for the changes to be replicated to all Domain Controllers before you will see the new user in the Active Directory Users and Computers MMC snap-in.

Adding a User Sample Code

try
{
string path = "LDAP://CN=Users,DC=dev,DC=codeguru,DC=com";
DirectoryEntry entry = new DirectoryEntry(path, 
"dev.codeguru.com\\administrator", "password");

// Create the user and set properties
DirectoryEntry user = entry.Children.Add("cn=Test User", "user");
user.Properties["sAMAccountName"].Add("testuser");
user.Properties["sn"].Add("User");
user.Properties["givenName"].Add("Test");
user.Properties["description"].Add("Test account added with code.");
user.CommitChanges();

// User has to be saved prior to this step
user.Invoke("SetPassword", new object[] {"mypassword1"} );

// Create a normal account and enable it - ADS_UF_NORMAL_ACCOUNT
user.Properties["userAccountControl"].Value = 0x200; 
user.CommitChanges();

}
catch( Exception exception )
{
Console.WriteLine( exception.Message );
}

Modifying a User

Modifying the properties of a user requires us to find an existing user, retrieve the directory entry for it, then make and commit the desired changes. When binding to the directory, we need to provide user credentials that have the authority to modify a user; otherwise, the update will fail.

If you have more than one Domain Controller, please allow time for the changes to be replicated to all Domain Controllers before you will see the new user in the Active Directory Users and Computers MMC snap-in.

Modifying a User Sample Code

try
{
  string path = "LDAP://CN=Users,DC=dev,DC=codeguru,DC=com";
  DirectoryEntry entry = new DirectoryEntry(path, 
  "dev.codeguru.com\\administrator", "password");
  DirectorySearcher search = new DirectorySearcher(entry);
  search.Filter = "(SAMAccountName=testuser)";
  SearchResult result = search.FindOne();
  DirectoryEntry user = result.GetDirectoryEntry();
  user.Properties["description"].Value = "New description for user";
  user.CommitChanges();
}
catch( Exception exception )
{
  Console.WriteLine( exception.Message );
}

Summary

You have now seen ways in which the DirectoryEntry and DirectorySearcher classes of the System.DirectoryServices namespace can be used to interact with directory services. We focused on the LDAP interface exposed by the Active Directory, but the examples can be made to work for different providers by changing the binding path.

Future Columns

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here, you can reach me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE (NT4/W2K), MCDBA is a Senior Architect of .NET applications for large- and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

# # #



About the Author

Mark Strawmyer

Mark Strawmyer is a Senior Architect of .NET applications for large and mid-size organizations. He specializes in architecture, design and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fifth year in a row. You can reach Mark at mark.strawmyer@crowehorwath.com.

Comments

  • His firm pumps take wickets colorblocking with multicolored zigzag and 4.7 heels. Jordan

    Posted by Vetriatszy on 03/15/2013 11:12am

    get the physique which lures in potential partners think it's great or, with associated with muscle mass can offer a poor glance. profoundly, even though women might be asked he or she hit upon too hard lean muscle a true turnoff. It is challenging to look "GQ" as well as "hip" after you have numerous a muscular body against your window frame. you've got the lot a muscular body that you won't ride in a typical set of pants, which continue reading. pregnant women opt Men with the standard degrees of muscle mass, over half of fantastic firmness. all those men or women each of the develop some thing in accordance. they each have a standard sum a muscular body. they even teach protect themselves fat heights good to signify with nice tone of muscle. this internal system aesthetics superb with on the other hand without the need laundry. wondering about doing exercises To terrific any other folks in your work out? i understand which looks ludicrous, nevertheless,having said that in my opinion the real reason why lads try can help provide as often lean muscle that they can. men are unquestionably cut-throat by nature, so end up competing with the other person in the gym placing along with. The recent dudes begin to see the more aged guy thanks to considerable arm rest, putting used household names and soon within spins that position mimic. they're going on a search for gain just as much muscular mass as you possibly can, before comprehending that doable a good hunt. Don't get up to date in a very "muscle tissue" trap and you will then get more Women! it is easy to get sucked into a voyage behind achieving the same amount of mass it can be. marvelous folks get fantastic value in the gym. you will note youth folks obtaining up to the experienced resources health in london. In the outside it certainly is not the exact. female accumulate think these guys appear witty. simply can not view interesting and include a number of muscle mass as well as! as you try to put on attractive look at this web-site or maybe cool fabric something looks a little "off from

    Reply
  • En Octobre de 2011, Abercrombie & Fitch a découvert Carly Rae "Bay Me Peut-être? et a lancé la chanson sur la bande son officielle the

    Posted by Vetriatszy on 03/14/2013 11:33am

    Abercrombie's advertisements certainly a layout web logs - search on "Abercrombie Fitch small children personal blogs" In search engines and yahoo. this certainly does supply hundreds and perhaps thousands as to web blog databases what individual completely describe in relation to Fitch garmets. this kind of specific internet sites supply you with swift having access to economical garments and they also may provide you a bunch of online codes used to have a great deal larger special discounts. every single single site visitor put in an individuals belief along with this company name because they're betting that each equipment seemed to be built and arranged from privileged health specialists inside the fashion sector. Abercrombie place jewelry stores is a lot of awe-inspiring factors to their potential customers. Abercrombie being giant aspects of the fashion operate in the abides of all individuals who need popular the gown that do it loss top rated quality more than fashion. if you are really looking towards expertise regal that is related to by hand and also are motivated to become an eye chocolate of each party, in which what are you watching for? that you must grab a bunch of real fantastic squeeze from the actual collection of?Abercrombie Fitch. Whether you prefer to keep fee with the actual fashion trends or your are merely wanting for consolation and simply grace, all Abercrombie material area am quite sure suit your preferences. one can find warmth, way and sturdiness, relying on the Abercrombie and Fitch product in order to meet your individual increased appetite. the truck driving Abercrombie Fitch business near you willing to give their customers some dresses not to mention layout does need. Abercrombie's posting evolving into a style, however needs to this content say its time honored, to discover a this kind of plenty which have owned and operated several of his Abercrombie outfits, shorts, Which are purchased in the US, child communicating, I'm hot for Abercrombie sales actions supporters. product sales team of college-outdated users do an amazing job at highlighting the entire occasional dress offered for sale quite great retailers Abercrombie Fitch. kinds inside of twenties 're also brilliant at portraying the frat together with sorority apartment feel like the earlier days today plan. things obtained as a store the actual cost of jacket meant for fishers, adventurers of all kinds, and / or rather huge competition searcher has recently began at command real estate among beginning some people's costumes. Ernest Hemingway used to acquire safari gowns from your F. To obtain a it is possible Hollister apparel real halloween costumes get on internet sites to choose from huge range of products offered by the online stores. might be an Abercrombie shop near you shop to your Abercrombie hair hoodies from a store

    Reply
  • Trouble when i create a directory entry

    Posted by David Serrano on 01/25/2013 08:27am

    I am using: private static DirectoryEntry ConsultarActiveDirectory(WindowsIdentity wi) { DirectoryEntry dir = new DirectoryEntry(); try { SecurityIdentifier sid = wi.User; dir = new DirectoryEntry("LDAP://"); System.Diagnostics.Trace.WriteLine("++++++++ Authenticacion in LDAP by " + (string)dir.Properties["distinguishedName"][0]); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine("++++++++ Error"+ ex.Message); throw; } return dir; } it works fine in local but from a remote machine it fails and i get: 'System.DirectoryServices.DirectoryServicesCOMException' how can i fix it? Thanks.

    Reply
  • How do I disabled a user list.

    Posted by Alejandra on 05/21/2012 05:25pm

    Hello. I need to disable a user list, but not all, not just one. For example the following users disable: userTest1, userTest2, userTest3, only this 3 users. Thanks :)

    Reply
  • Problem in setting the password for a user in active directory

    Posted by AvanishG on 11/16/2006 06:44am

    I'm facing a problem when setting a password for newly cretaed user to AD. Below is th code, i'm using to set.. newuser.Invoke("SetPassword", new object[] {"password"}); The error i get is "[System.Reflection.TargetInvocationException] = {"Exception has been thrown by the target of an invocation."}" and inner exception is "InnerException = {"You were not connected because a duplicate name exists on the network. Go to System in Control Panel to change the computer name and try again. (Exception from HRESULT: 0x80070034)"}" Can anybody tell me, what/where is the problem? Thanks in advance

    • Refer this link for solution

      Posted by kanzariya_shailesh on 09/30/2008 05:06am

      http://forums.asp.net/t/968051.aspx
      
      if link does not workb&b&
      
      What I actually did to fix this is after creating the account and committing that change, I created a new DirectoryEntry  (newUserEntry) object based on the newly created account and then set the password.
      
      //This works:
      
      DirectoryEntry adEntry = new DirectoryEntry(targetPath, "administrator", "password");
      DirectoryEntry userEntry = adEntry.Children.Add(sourceNode.Name, "User");
      userEntry.CommitChanges();
      DirectoryEntry newUserEntry = new DirectoryEntry(userEntry.Path, "administrator", "password");
      string password = "password";
      newUserEntry.Invoke("SetPassword", new object[] { password });
      newUserEntry.CommitChanges();

      Reply
    • Problem in setting the password for a user in active directory

      Posted by esther.uj on 07/28/2008 12:44am

      Does anyone have the answer for this problem? I also face the same problem? Anyone have the solution? Thanks in advanced.

      Reply
    Reply
  • I can't add new user using LDAP?

    Posted by BigBird on 06/09/2006 04:58am

    My pc have been promos to DC  
    and domain name is fbf.com
    if i use WinNT Provider i can add a user like this
    
    obDirEntry = new DirectoryEntr("WinNT://fbf.com/fbftungnc");
    			
    DirectoryEntries entries = obDirEntry.Children;
    
    DirectoryEntry objUser = entries.add(strLogin,"User");
    
    entries.Comitchanges();
    
    but if i using LDAP
    
    string path = "LDAP://CN=users,DC=fbf,DC=com";
    DirectoryEntry entry = new DirectoryEntry(path,
    "fbf.com\\administrator", "tungnc");
    DirectoryEntry ouser = entry.Children.Add("FSS", "user");
    ouser.CommitChanges();//error
    
    it alway seend a error message
    "an invalid dn syntax have been specified"
    
    could you show me why??
                  Thanks and regard!

    • I can't add new user using LDAP?

      Posted by Carlos Bomtempo on 10/26/2012 12:40pm

      I know that years have passed, but maybe someone having this problems arrives here. To solve the XXX problem, change the entry.Children.Add line to be like this: DirectoryEntry ouser = entry.Children.Add("CN=FSS", "user");

      Reply
    Reply
  • How do i get my hands on the email?

    Posted by zatopek on 04/06/2006 04:17am

    I need to change a lot of email adresses. Is there an easy way of doing it using this approach? I want yo get all the aliases for the found user, and maybee to add new.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Is your sales and operations planning helping or hurting your bottom line? Here are 5 useful tips from the experts at Quintiq to guide you to a better S&OP strategy.

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today make data protection a must-have, as we live in a data driven society. The digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join eVault Chief Technology …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds