如何使用C#更好地查询Active Directory中的多个域?

我正在尝试将LDAP / AD搜索从仅在当前登录的域中搜索扩展到搜索AD中的所有域。 该方法接受带有查询的字符串,并返回并返回LDAPInformation对象。

虽然我在问,有没有更好的方法来搜索名称而不是这种方式? 如果用姓氏寻找一个人需要使用通配符,这是用户不友好的(例如:Doe *)。

public static LDAPInformation[] GetGlobalAddressListVIAName(string nameQuery) { var currentForest = Forest.GetCurrentForest(); var globalCatalog = currentForest.FindGlobalCatalog(); using (var searcher = globalCatalog.GetDirectorySearcher()) { using (var entry = new DirectoryEntry(searcher.SearchRoot.Path)) { searcher.Filter = "(&(mailnickname=*)(objectClass=user)(displayName=" + nameQuery + "))"; searcher.PropertyNamesOnly = true; searcher.SearchScope = SearchScope.Subtree; searcher.Sort.Direction = SortDirection.Ascending; searcher.Sort.PropertyName = "displayName"; return searcher.FindAll().Cast().Select(result => new LDAPInformation(result.GetDirectoryEntry())).ToArray(); } } } 

这是对象:

  class LDAPInformation { internal LDAPInformation(DirectoryEntry entry) { //Section: HASH this.sAMAccountName = (string)entry.Properties["sAMAccountName"].Value; //Section: Email this.Mail = (string)entry.Properties["mail"].Value; //Section: Organziation this.Description = (string)entry.Properties["description"].Value; this.Company = (string)entry.Properties["company"].Value; this.Title = (string)entry.Properties["title"].Value; this.Department = (string)entry.Properties["department"].Value; //Section: Name this.DisplayName = (string)entry.Properties["displayName"].Value; this.FirstName = (string)entry.Properties["firstName"].Value; this.MiddleName = (string)entry.Properties["middleName"].Value; this.LastName = (string)entry.Properties["lastName"].Value; //Section: Address this.StreetAddress = (string)entry.Properties["streetAddress"].Value; this.City = (string)entry.Properties["city"].Value; this.State = (string)entry.Properties["state"].Value; this.PostalCode = (string)entry.Properties["postalCode"].Value; this.TelephoneNumber = (string)entry.Properties["telephoneNumber"].Value; } public string DisplayName { get; private set; } public string Mail { get; private set; } public string sAMAccountName { get; private set; } public string Description { get; private set; } public string Company { get; private set; } public string Title { get; private set; } public string Department { get; private set; } public string FirstName { get; private set; } public string MiddleName { get; private set; } public string LastName { get; private set; } public string StreetAddress { get; private set; } public string City { get; private set; } public string State { get; private set; } public string PostalCode { get; private set; } public string TelephoneNumber { get; private set; } } 

查询全局编录是正确的方法。

您可能需要查看Ambigous Name Resolution(ANR) – http://support.microsoft.com/kb/243299

@Brian Desmond和@lordzero。 可能有点迟到了,但我最近一直在研究这种东西,所以我想分享。

回答你的问题“你的搜索根目录是什么?”,lordzero,你可以在不知道的情况下从AD服务器上找到它。域名注册的PC将知道AD基础设施/森林等。

首先,为“GC:// rootDSE”创建一个DirectoryEntry,从中提取命名上下文,rootDomainNamingContext或其他。 您可以转储第一个根DSE DirectoryEntry的所有属性,以查看可用的内容。

这是我对我们使用的目录服务服务提供商的实现。

这是从DirectorySearcherWrapper类中获取的

我有一个成员var。 并在构造函数中实例化它。

 DirectorySearcher directorySearcher; 

在我的初始化方法中,我这样做

  using (DirectoryEntry directoryEntry = new DirectoryEntry(DirectoryConstants.RootDSE)) { // Create a Global Catalog Directory Service Searcher string strRootName = directoryEntry.Properties[DirectoryConstants.RootDomainNamingContext].Value.ToString(); using (DirectoryEntry usersBinding = new DirectoryEntry(DirectoryConstants.GlobalCatalogProtocol + strRootName)) { directorySearcher.SearchRoot = usersBinding; directorySearcher.ClientTimeout = timeout; directorySearcher.CacheResults = true; result = true; initialized = true; } } 

DirectoryConstants类属性

 public static string RootDSE { get { return @"GC://rootDSE"; } } public static string RootDomainNamingContext { get { return "rootDomainNamingContext"; } } public static string GlobalCatalogProtocol { get { return @"GC://"; } } 

我确信这仅适用于登录到域注册PC的域用户。 在后台自动处理身份validation。 如果您的用户登录到本地帐户或该计算机不在域上,您很可能会获得DirectoryServicesCOMException。

希望这可以帮助。 如果您对处理和StyleCop / Sonar编码违规行为不感兴趣,请放弃“使用”结构!

然后,服务提供者代码使用上面代码所在的DirectorySearcherWrapper类。 它是这样分开的,所以它很容易被模拟,因为在执行我们的unit testing时无法保证构建机器注册到域。

…大部分来自MSDN / .Net文档。