Searching for User Objects


In the final section of this chapter, you build a Windows Forms application called UserSearch. This application is flexible insofar as a specific domain controller, username, and password to access the Active Directory can be entered; otherwise, the user of the running process is used. In this application, you access the schema of the Active Directory service 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 (see Figure 42-15):

  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 list box.

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

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

  5. Now the search can start.

image from book
Figure 42-15

Get the Schema Naming Context

This application has only two handler methods: one method for the button to load the properties and one to start the search in the domain. First, you 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 host name from the dialog box 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 list box: SetUserProperties().

  private void OnLoadProperties(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(), you are using the root of the directory tree to get the properties of the server. You are interested only in the value of two properties: schemaNamingContext and defaultNamingContext.

  protected void 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

You have the LDAP name to access the schema. You can use this to access the directory and read the properties. You are not only interested in the properties of the user class but also those of the base classes of user: Organizational-Person, Person, and Top. In this program, the names of the base classes are hard-coded. You could also 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) {    List<string> properties = new List<string>();    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(), you are accessing the Active Directory service again. This time rootDSE is not used but rather the LDAP name to the schema that you 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 preceding 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, the namespace name can be shortened as follows:

  using DS = System.DirectoryServices; 

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

Search for User Objects

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

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

In FillResult(), you do a normal search in the complete Active Directory Domain as you saw earlier. SearchScope is set to Subtree, the Filter to the string you get from a TextBox object, and the properties that should be loaded into the cache are set by the values the user selected in the list box. The method GetProperties() that is used to pass an array of properties to the method searcher.PropertiesToLoad .AddRange() is a helper method that reads the selected properties from the list box into an array. After setting the properties of the DirectorySearcher object, the properties are searched by calling the SearchAll() method. The result of the search inside the SearchResultCollection is used to generate summary information that is written to the text box textBoxResults:

  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 gives you a list of all objects where the filter is valid (see Figure 42-16).

image from book
Figure 42-16




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

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