Searching for User Objects

 
Chapter 13 - Working with the Active Directory
bySimon Robinsonet al.
Wrox Press 2002
  

Searching for User Objects

In the final section of this chapter we will build a Windows Forms application called UserSearch . This application is flexible in that a specific domain controller, username, and password to access the Active Directory can be entered, or the user of the running process is used. In this application we will access the schema of the Active Directory to get the properties of a user object. The user can enter a filter string to search all user objects of a domain. It's also possible to set the properties of the user objects that should be displayed.

User Interface

The user interface shows numbered steps to indicate how to use the application:

  1. In the first step Username , Password , and the Domain Controller can be entered. All this information is optional. If no domain controller is entered the connection works with serverless binding. If the username is missing the security context of the current user is taken.

  2. A button allows all the property names of the user object to be loaded dynamically in the listBoxProperties listbox.

  3. After the property names are loaded, the properties that should be displayed can be selected. The SelectionMode of the listbox is set to MultiSimple .

  4. The filter to limit the search can be entered. The default value that's set in this dialog box searches for all user objects: (objectClass=user) .

  5. Now the search can start:

    click to expand

Get the Schema Naming Context

This application just has two handler methods : the first handler method for the button to load the properties, and the second to start the search in the domain. In the first part we read the properties of the user class dynamically from the schema to display it in the user interface.

In the handler buttonLoadProperties_Click() method, SetLogonInformation() reads the username, password, and hostname from the dialog and stores them in members of the class. Next the method SetNamingContext() sets the LDAP name of the schema and the LDAP name of the default context. This schema LDAP name is used in the call to set the properties in the listbox: SetUserProperties() :

   private void buttonLoadProperties_Click(object sender, System.EventArgs e)     {     try     {     SetLogonInformation();     SetNamingContext();     SetUserProperties(schemaNamingContext);     }     catch (Exception ex)     {     MessageBox.Show("Check your inputs! " + ex.Message);     }     }     protected void SetLogonInformation()     {     username = (textBoxUsername.Text == "" ? null : textBoxUsername.Text);     password = (textBoxPassword.Text == "" ? null : textBoxPassword.Text);     hostname = textBoxHostname.Text;     if (hostname != "") hostname += "/";     }   

In the helper method SetNamingContext() , we are using the root of the directory tree to get the properties of the server. We are just interested in the value of two properties: schemaNamingContext and defaultNamingContext :

   protected string SetNamingContext()     {     using (DirectoryEntry de = new DirectoryEntry())     {     string path = "LDAP://" + hostname + "rootDSE";     de.Username = username;     de.Password = password;     de.Path = path;     schemaNamingContext = de.Properties["schemaNamingContext"][0].ToString();     defaultNamingContext =     de.Properties["defaultNamingContext"][0].ToString();     }     }   

Get the Property Names of the User Class

We have the LDAP name to access the schema. We can use this to access the directory and read the properties. We are not only interested in the properties of the user class, but also of the base classes of user : Organizational-Person , Person , and Top . In this program, the names of the base classes are hard-coded. It would be also possible to read the base class dynamically with the subClassOf attribute. GetSchemaProperties() returns a string array with all property names of the specific object type. All the property names are collected in the StringCollection properties:

   protected void SetUserProperties(string schemaNamingContext)     {     StringCollection properties = new StringCollection();     string[] data = GetSchemaProperties(schemaNamingContext, "User");     properties.AddRange(GetSchemaProperties(schemaNamingContext,     "Organizational-Person"));     properties.AddRange(GetSchemaProperties(schemaNamingContext, "Person"));     properties.AddRange(GetSchemaProperties(schemaNamingContext, "Top"));     listBoxProperties.Items.Clear();     foreach (string s in properties)     {     listBoxProperties.Items.Add(s);     }     }   

In GetSchemaProperties() we are accessing the Active Directory again. This time rootDSE is not used, rather the LDAP name to the schema that we discovered earlier. The property systemMayContain holds a collection of all attributes that are allowed in the class objectType :

   protected string[] GetSchemaProperties(string schemaNamingContext,     string objectType)     {     string[] data;     using (DirectoryEntry de = new DirectoryEntry())     {     de.Username = username;     de.Password = password;     de.Path = "LDAP://" + hostname + "CN=" + objectType + "," +     schemaNamingContext;     DS.PropertyCollection properties = de.Properties;     DS.PropertyValueCollection values = properties["systemMayContain"];     data = new String[values.Count];     values.CopyTo(data, 0);     }     return data;     }   

Note the presence of DS.PropertyCollection in the above code - this is because in a Windows Forms application, the PropertyCollection class of the System.DirectoryServices namespace has a naming conflict with System.Data.PropertyCollection , and to avoid long names like System.DirectoryServices.PropertyCollection, I shortened the namespace name using the following:

   using DS = System.DirectoryServices;   

Step 2 in the application is completed. The listbox has all the property names of the user objects.

Search For User Objects

The handler for the search button just calls the helper method FillResult() :

   private void buttonSearch_Click(object sender, System.EventArgs e)     {     try     {     FillResult();     }     catch (Exception ex)     {     MessageBox.Show("Check your input: " + ex.Message);     }     }   

In FillResult() we are doing a normal search in the complete Active Directory Domain as we've seen earlier. SearchScope is set to Subtree , the Filter to the string we get from a TextBox , and the properties that should be loaded into the cache are set by the values the user selected in the listbox:

   protected void FillResult()     {     using (DirectoryEntry root = new DirectoryEntry())     {     root.Username = username;     root.Password = password;     root.Path = "LDAP://" + hostname + defaultNamingContext;     using (DirectorySearcher searcher = new DirectorySearcher())     {     searcher.SearchRoot = root;     searcher.SearchScope = SearchScope.Subtree;     searcher.Filter = textBoxFilter.Text;     searcher.PropertiesToLoad.AddRange(GetProperties());     SearchResultCollection results = searcher.FindAll();     StringBuilder summary = new StringBuilder();     foreach (SearchResult result in results)     {     foreach (string propName in     result.Properties.PropertyNames)     {     foreach (string s in result.Properties[propName])     {     summary.Append(" " + propName + ": " + s + "\r\n");     }     }     summary.Append("\r\n");     }     textBoxResults.Text = summary.ToString();     }     }     }   

Starting the application we get a list of all objects where the filter is valid:

click to expand
  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net