Skip to main content
Email Password   helpLost your password?

Sample Image - ActiveDirQueryDemo.jpg

Introduction

This article describes how to use .NET framework to manage resources under Windows Active Directory Services. Microsoft provides ADSI (Active Directory Services Interface) which can interact with many providers including IIS (Internet Information Services), LDAP (Lightweight Directory Access Protocol), WinNT and NDS (Novell Netware Directory Service).
Since my aim is to demonstrate the usage of .NET DirectoryService classes I am restricting the demo project to querying some commonly used resources (computers, users and printers) in the domain where the user's machine is, at the same time demonstrating the power of Active Directory services and the ease with which Active Directory objects can be retrieved.

I have also used LDAP in this demo since I thought that it will be useful to know this protocol as it is a platform independent protocol.

There are different ways to query the Active Directory Services in a C# program

.NET System.DirectoryServices namespace

The System.DirectoryServices namespaces provides two important classes DirectoryEntry and DirectorySearcher to work with the Active Directory. The DirectoryEntry class represents a resource in the Active Directory and the DirectorySearcher class is used to query the Active Directory. The other classes under this namespace are for .NET security and collection classes to support the above said main classes.
You have to add System.DirectoryServices to your references by selecting System.DirectoryServices.dll from .NET tab in the Add Reference dialog box.

LDAP format filter strings

The DirectorySearcher class uses a search root which is a server where the search begins and a LDAP filter string (which is analogous to where clause in SQL) to query the Active Directory resources. LDAP format filter strings are similar to LISP. A condition is enclosed by parenthesis and an operator precedes 2 conditions. Eg. (& (A)(B)) The statement is equivalent to saying A and B. Remember the parenthesis. Another example (| (& (A)(B) ) (C) ) should be interpreted as (A and B) or (C).

The OLAP conditional statements are formed by using Active Directory attributes like name, objectCategory, objectClass, printerName, ListedName etc. For eg. to query for a list of printers the condition would be (objectCategory=printQueue) where objectCategory is an attribute and printQueue is the value expected to be assigned to a printer resource in Active Directory. Similary to query for all printers which start with a character 'G' the LDAP query would be (& (objectCategory=printQueue) (name=G*) ) In the above filter observe that the values do not have quotes (' or ") around them.

Using the code

The demo project demonstrates how to query the Active Directory Services and fetch different objects. The LDAP queries and the usage of .NET classes used are confined to QueryObjectsByNETClasses() and GetFilterString() methods.

The following code in QueryObjectsByNETClasses() method creates a DirectorySearcher object and sets properties on the searcher depending on the user preferences given in the main form. The description of different properties is in the comments in the code. Only "name" is added to the PropertiesToLoad property of DirectorySearcher class to save time as we are only interested in retrieving name and objectClass for the list of objects returned.

    DirectorySearcher ds = new DirectorySearcher();
    ds.SearchRoot = new DirectoryEntry("");    
      // start searching from local domain

    ds.Filter = GetFilterString();        
      // get the LDAP filter string based on selections on the form

    ds.PropertyNamesOnly = true;        
      // this will get names of only those 

      // properties to which a value is set

    ds.PropertiesToLoad.Add("name");

    // (PageSize) Maximum number of objects 

    // the server will return per page

    // in a paged search. Default is 0, i.e. no paged search

    if (ObjsPerPage.Text.Length > 0) 
        ds.PageSize = Int32.Parse(ObjsPerPage.Text);

    // (ServerPageTimeLimit) the amount of time the server

    // should observe to search a page of results

    // default is -1, i.e. search indefinitely

    if (PageTimeLimit.Text.Length > 0) 
        ds.ServerPageTimeLimit = new TimeSpan((long)(Decimal.Parse(
            PageTimeLimit.Text) * TimeSpan.TicksPerSecond));

    // (SizeLimit) maximum number of objects the server 

    // returns in a search

    // default is 0 - interpreted as server 

    // set default limit of 1000 entries

    if (ObjsToFetch.Text.Length > 0) 
        ds.SizeLimit = Int32.Parse(ObjsToFetch.Text);

    // (ServerTimeLimit) amount of time that the server 

    // should observe in a search

    // default is -1 interpreted as server default limit of 120 seconds 

    if (TotalTimeLimit.Text.Length > 0) 
        ds.ServerTimeLimit = new TimeSpan((long)(Decimal.Parse(
           TotalTimeLimit.Text) * TimeSpan.TicksPerSecond));

    // (SearchScope) option to search one level or complete subtree

    // default is Subtree, so set this option only if oneLevel is selected

    if (searchOptionCB.SelectedIndex == 1)
        ds.SearchScope = SearchScope.OneLevel;

    // (CacheResults) property by default is true

    ds.CacheResults = CacheResultsCB.Checked;

    ds.ReferralChasing = ReferralChasingOption.None;

    if (SortResultsCB.Checked)
        ds.Sort = new SortOption("name", SortDirection.Ascending);

The FormFilter() and GetFilterString() functions are used to form the LDAP query strings (see the explaination for the format of these strings in the LDAP format filter strings section above). Mainly observe the placement of & and | operators before the lists. For a complete set of attributes on which the queries can be formed for different objects refer to the Active Directory Schema under MSDN here.

    // form a filter string for the search in LDAP format

    private string FormFilter(string objectCategory, string filter)
    {
        String result;
        result = String.Format("(&(objectCategory={0})(name={1}))", 
           objectCategory, filter);
        return result;
    }

    // this function forms the filter string based on the selected

    // objects on the form

    private string GetFilterString()
    {
        // form the filter string for directory search

        string filter = "";
        if (UsersCB.Checked)
            filter += FormFilter("user", UsersFilter.Text);
        if (ComputersCB.Checked)
            filter += FormFilter("computer", ComputersFilter.Text);
        if (PrintersCB.Checked)
            filter += FormFilter("printQueue", PrintersFilter.Text);

        // add all the above filter strings

        return "(|" + filter + ")";
    }

Important Points and Notes

The second point is more important because all the examples given in MSDN use objectClass, whereas using objectCategory will speed up queries !

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionVersion for Visual Studio 08 Pin
tbark
16:55 27 Jan '09  
JokeRe: Version for Visual Studio 08 Pin
CoderGirl42
13:15 26 Mar '09  
GeneralHow to get other information of the user Pin
dabuskol
21:49 2 Dec '08  
GeneralUser Creation Help Required (mukatys@yahoo.com) Pin
Asif Mukaty
21:38 17 Jun '08  
GeneralSolution for other LDAP servers Pin
wojtekp
20:53 22 Feb '08  
GeneralCan't open it b/c it says I have the wrong .Net runtime version Pin
bort1983
11:02 27 Jul '07  
GeneralActive computers Pin
Mubshir Raza Ali
3:18 6 Jul '07  
GeneralNested groups Pin
Refky Wahib
0:02 3 Apr '07  
Questionldap filter size Pin
siedell
11:14 12 Dec '06  
GeneralExcelente! (Great!) Pin
goarango
10:04 27 Nov '06  
GeneralThank you Sriram! Pin
ssudhaa
7:25 7 Nov '06  
QuestionHow I can get a good list of attributes and filter criteria? Pin
William Yeung
2:09 10 Oct '06  
AnswerRe: How I can get a good list of attributes and filter criteria? Pin
Duoc BT
14:54 26 Oct '06  
GeneralDelete user AD [modified] Pin
Bigbirdtung
1:33 6 Jun '06  
GeneralCan't conect to DC from LAN Pin
Bigbirdtung
1:15 6 Jun '06  
AnswerRe: Can't conect to DC from LAN Pin
zohaibabrar
23:35 22 Sep '06  
GeneralSize Limit Pin
cavedog6
6:06 5 Jun '06  
GeneralRe: Size Limit Pin
andreas.eppinger
0:39 27 Jun '06  
GeneralRe: Size Limit Pin
Marlon Rodriguez
17:46 20 Jul '06  
GeneralRe: Size Limit Pin
jportelas
8:41 29 Jan '07  
AnswerRe: Size Limit Pin
andreas.eppinger
10:55 29 Jan '07  
GeneralRe: Size Limit Pin
jportelas
3:28 30 Jan '07  
GeneralLDAP Query for Groups in Active Directory Pin
chitransh
1:43 2 Jun '06  
AnswerRe: LDAP Query for Groups in Active Directory Pin
vinodjnair
0:59 26 Sep '06  
GeneralRe: LDAP Query for Groups in Active Directory Pin
soup1983
10:18 18 Dec '06  


Last Updated 30 May 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009