10

我正在使用这些System.DirectoryServices.ActiveDirectory类来查找所有 Active Directory 用户。代码非常简单:

var context = new PrincipalContext(ContextType.Domain);
var searcher = new PrincipalSearcher(new UserPrincipal(context));
var results = searcher.FindAll();

我想以“友好”(又名“pre-Windows 2000”格式)获取域限定的用户名,例如。“CONTOSO\SmithJ”。UserPrincipal.SamAccountName给了我用户名部分,但我如何获得域部分?我不能假设域与机器或当前用户的域相同。

4

2 回答 2

7

对于 AD DS, 的值msDS-PrincipalName是 NetBIOS 域名,后跟反斜杠 ("\")。

您可以使用以下方法找到它:

/* Retreiving the root domain attributes
 */ 
sFromWhere = "LDAP://DC_DNS_NAME:389/dc=dom,dc=fr"; 
DirectoryEntry deBase = new DirectoryEntry(sFromWhere, "AdminLogin", "PWD"); 

DirectorySearcher dsLookForDomain = new DirectorySearcher(deBase); 
dsLookForDomain.Filter = "(objectClass=*)"; 
dsLookForDomain.SearchScope = SearchScope.base; 
dsLookForDomain.PropertiesToLoad.Add("msDS-PrincipalName"); 

SearchResult srcDomains = dsLookForDomain.FindOne();
于 2012-05-22T17:47:22.133 回答
0

好的,这是我使用 JPBlanc 的答案和MichaelZ 链接的答案得出的最终代码。它显示每个用户的 SID、显示名称和域\用户名。

    var ldapUrl = "LDAP://" + defaultNamingContext;

    using (var rootDe = new DirectoryEntry(ldapUrl))
    using (var searcher = new DirectorySearcher(rootDe))
    {
        searcher.SearchScope = SearchScope.Subtree;
        searcher.PropertiesToLoad.Add("objectSid");
        searcher.PropertiesToLoad.Add("displayName");
        searcher.PropertiesToLoad.Add("msDS-PrincipalName");
        searcher.Filter = "(&(objectClass=user)(objectCategory=person))";

        var results = searcher.FindAll();

        foreach (SearchResult result in results)
        {
            var qualifiedUsername = GetSinglePropertyValue(result, "msDS-PrincipalName");
            var displayName = GetSinglePropertyValue(result, "displayName");
            var sid = new SecurityIdentifier((byte[])GetSinglePropertyValue(result,"objectSid"), 0);

            Console.WriteLine("User: {0}\r\n\tDisplay name: {1}\r\n\tSID: {2}",
                qualifiedUsername, displayName, sid);
        }
    }

    private static object GetSinglePropertyValue(SearchResult result, string propertyName)
    {
        var value = result.Properties[propertyName];
        if (value.Count == 0)
            return null;
        if (value.Count == 1)
            return value[0];
        throw new ApplicationException(string.Format("Property '{0}' has {1} values for {2}",
            propertyName, value.Count, result.Path));
    }

并获取机器域的默认命名上下文(如此处回答):

private static string GetDefaultNamingContext()
{
    // This check is fast
    try
    {
        Domain.GetComputerDomain();
    }
    catch (ActiveDirectoryObjectNotFoundException)
    {
        return null;
    }

    // This takes 5 seconds if the computer is not on a domain
    using (var rootDe = new DirectoryEntry("LDAP://RootDSE"))
    {
        try
        {
            return (string)rootDe.Properties["defaultNamingContext"][0];
        }
        catch (COMException ex)
        {
            if (ex.ErrorCode == -2147023541)
                return null;
            throw;
        }
    }
}
于 2012-05-26T12:40:15.210 回答