当 AD/NT 用户不存在时,DirectoryEntry.Exist 在 C# 中花费超过 10 秒的时间

DirectoryEntry.Exist in C# taking more than 10 Sec time when AD/NT user is not present

问题也可以通过以下简单应用程序触发:

Stopwatch watch = new Stopwatch();
string[] userNames = {"JunkName", "DummyName"};

foreach (var name in userNames)
{
    watch.Reset();
    watch.Start();

    if (DirectoryEntry.Exists("WinNT://" + Environment.MachineName + "/" + name))
    {
        Console.WriteLine($"user {name} found in " + watch.ElapsedMilliseconds + "ms");
    }
    else
    {
        Console.WriteLine($"user {name} not found in " + watch.ElapsedMilliseconds + "ms");
    }
}

没有正确的根本原因可以判断是 Microsoft API 问题还是其他问题。

然而,大多数搜索结果都提到如果您搜索一个不存在的用户,而不是 return false,DirectoryEntry.Exists 方法将抛出异常。

但在我们的示例应用程序中它没有抛出任何异常。

我还尝试了以下一些建议来检查这些示例代码需要多少执行时间,发现这些代码第一次也需要超过 11 秒。

示例 1:

using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
{
    UserPrincipal up = UserPrincipal.FindByIdentity(pc,
                    IdentityType.SamAccountName, name);
 
    UserExists = (up != null);
}

示例 2:

DirectoryEntry dirEntryLocalMachine =
    new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
 
bool UserExists =
    dirEntryLocalMachine.Children.Find(userIdentity, "user") != null;

只是高度怀疑 OS 更新会导致问题,可能是我的假设是错误的。

提前致谢

有一天我遇到了同样的延迟,所以我写了这个更快的函数,也许它可以帮助你:

    private string FindUserSID(string domain, string user)
    {
        string output;

        try
        {
            NTAccount account = new NTAccount(domain + @"\" + user);
            SecurityIdentifier s = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
            output = s.ToString();
        }
        catch (IdentityNotMappedException)
        {
            output = null;
        }

        return output;
    }