0

我正在使用此代码填充 Active Directory 用户的组合框,但有时我会在代码有效旁边的“for each”处收到 COM 异常。

System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://DC=DOMAIN, DC=local");
System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=user)(objectCategory=person))";

foreach (System.DirectoryServices.SearchResult resEnt in mySearcher.FindAll())
{
   try
   {
       //DirectoryEntry de = new DirectoryEntry(resEnt.GetDirectoryEntry());
       System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
       comboBox2.Items.Add(de.Properties["GivenName"].Value.ToString() + " " + de.Properties["sn"].Value.ToString() + " " + "[" + de.Properties["sAMAccountName"].Value.ToString() + "]");
   }
   catch (Exception e)
   {
       // MessageBox.Show(e.ToString());
   }
}

有没有更有效的方法来执行此操作或解决错误?

4

2 回答 2

4

我要做的第一件事是将要从结果中获取的属性包含到搜索结果中 - 这样,您就不必.GetDirectoryEntry()对每个结果进行调用:

using System.DirectoryServices;

DirectoryEntry entry = new DirectoryEntry("LDAP://DC=DOMAIN, DC=local");

DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=user)(objectCategory=person))";

// define the properties you want to be loaded into the search result object
mySearcher.PropertiesToLoad.Add("GivenName");
mySearcher.PropertiesToLoad.Add("samAccountName");
mySearcher.PropertiesToLoad.Add("sn");

foreach (SearchResult resEnt in mySearcher.FindAll())
{
   try
   {
       string givenName = "";
       string samAccountName = "";
       string surName = "";

       // check if you got a value - not all properties have to be filled - 
       // and if they're not filled, they might be "null". 
       if(resEnt.Properties["GivenName"] != null && 
          resEnt.Properties["GivenName"].Count > 0) 
       {
           givenName = resEnt.Properties["GivenName"].Value;
       }

       // samAccountName is a *must* property - it has to be set.
       samAccountName = resEnt.Properties["samAccountName"].Value;

       if(resEnt.Properties["sn"] != null && 
          resEnt.Properties["sn"].Count > 0) 
       {
           surName = resEnt.Properties["sn"].Value;
       }

       comboBox2.Items.Add(givenName + " " + surName + " " + "[" + samAccountName + "]");
   }
   catch (Exception e)
   {
       // MessageBox.Show(e.ToString());
   }
}

The second point is: if you're on .NET 3.5 or newer, you can use a PrincipalSearcher and a "query-by-example" principal to do your searching; also, working with the result set using the UserPrincipal objects is a lot easier, since things like GivenName and Surname are surfaced as properties on the UserPrincipal:

// create your domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// define a "query-by-example" principal - here, we search for any UserPrincipal 
UserPrincipal qbeUser = new UserPrincipal(ctx);

// create your principal searcher passing in the QBE principal    
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);

// find all matches
foreach(var found in srch.FindAll())
{
    // do whatever here 
    UserPrincipal foundUser = found as UserPrincipal;

    if(foundUser != null)
    {
       comboBox2.Items.Add(foundUser.GivenName + " " + foundUser.Surname + " " + "[" + foundUser.SamAccountName + "]");
    }
}

If you haven't already - absolutely read the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 which shows nicely how to make the best use of the new features in System.DirectoryServices.AccountManagement. Or see the MSDN documentation on the System.DirectoryServices.AccountManagement namespace.

Of course, depending on your need, you might want to specify other properties on that "query-by-example" user principal you create:

  • DisplayName (typically: first name + space + last name)
  • SAM Account Name - your Windows/AD account name
  • User Principal Name - your "username@yourcompany.com" style name

You can specify any of the properties on the UserPrincipal and use those as "query-by-example" for your PrincipalSearcher.

于 2012-09-19T19:43:32.683 回答
0

将 foreach 循环放在 try...catch 语句的 catch 块中。

于 2012-09-19T19:11:07.867 回答