DirectorySearcher.ClientTimeout - 搜索超时或真的0结果?

时间:2016-09-13 17:27:35

标签: c# active-directory

我维护一个C#程序,需要检查是否仍存在数千个Active Directory帐户。如果它们被启用或不启用。最近,我发现我的程序在查询帐户目录时挂起了。幸运的是,我刚刚发现DirectorySearcher.ClientTimeout属性(我没有设置,这意味着搜索无限期地继续)。

我在使用此属性时遇到的一个问题是,如果搜索在查找实际存在的帐户时挂起,则DirectorySearcher.FindOne()方法将返回0结果。您可以想象,这是一个问题,因为在运行时,我不知道搜索是否失败或者是否确实找不到该帐户。

有没有人知道是否在对象中设置了另一个属性,我可以用它来查看搜索是否中止了?中止搜索的结果集与真正包含零结果的结果集之间是否存在差异?

这是我的方法:

public static string UserExists(string username, Log log)
    {
        string accountStatus;

        if (username.Split('\\').Length != 2)
            return "Invalid ID,Invalid ID";
        else
        {
            try
            {
                string[] parts = username.Split('\\');
                domain = parts[0];
                ScopeDN = "DC=" + domain + ",DC=contoso,DC=com";
                DirectoryEntry de = GetDirectoryEntry("LDAP://" + ScopeDN);
                DirectorySearcher ds = new DirectorySearcher();
                ds.SearchRoot = de;
                ds.ClientTimeout = TimeSpan.FromSeconds(30);
                ds.Filter = "(&(objectClass=user) (sAMAccountName=" + username + "))";

                SearchResult result = ds.FindOne();

                if (result == null)
                    accountStatus = "Does Not Exist,Account Does Not Exist";
                else
                {
                    int UAC = (int)result.Properties["userAccountControl"][0];

                    bool enabled = !Convert.ToBoolean(UAC & 0x00002);
                    if (enabled)
                        accountStatus = "Exists,Account is Enabled";
                    else
                        accountStatus = "Exists,Account is Disabled";
                }

                return accountStatus;
            }
            catch (Exception e)
            {
                log.exception(LogLevel._ERROR, e, false);
                return "Exception,Exception";
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

尝试执行以下优化:

  • Dispose DirectoryEntry
  • Dispose DirectorySearcher
  • 在查询用户之前创建并缓存与RootDse对象的连接。在这种情况下,所有AD查询都将使用一个到AD的单个缓存连接,这可以显着提高性能。

例如

var entry = new DirectoryEntry("LDAP://contoso.com/RootDSE");
entry.RefreshCache();
// making user search and other AD work with domain contoso.com here
entry.Dispose();

答案 1 :(得分:0)

AFAIK,没有区别。你可以做的一件事是在假设它丢失之前重试几次。这是一个充满信心的问题。一次失败可能无法给予足够高的信心。但是2或3可能。这对你有帮助吗?