我正在尝试查询Active Directory并返回一个IEnumerable,但具有Title和EmailAddress等属性,这些属性在PrincipalSearcher.Findll((中没有显示。如果我使用 PrincipalSearcher.FindOne((,它有更多的属性(虽然仍然不是 Title(,所以我试图弄清楚我在做什么不同或如何获取我需要的信息。我已经厌倦了谷歌试图找到更多信息,似乎UserPrincipal.GetUnderlyingObject((可能是票证,但我不明白如何将其纳入foreach循环以将其填充到列表中。
public class ADUser
{
public string SamAccountName { get; set; }
public string DisplayName { get; set; }
public string Title { get; set; }
public IEnumerable<ADUser> Get(string username)
{
var users = new List<ADUser>();
var principalContext = new PrincipalContext(ContextType.Domain, "domain.com");
var userPrincipal = new UserPrincipal(principalContext)
{
SamAccountName = username
};
var principalSearcher = new PrincipalSearcher(userPrincipal);
foreach (var user in principalSearcher.FindAll())
{
users.Add(new ADUser
{
SamAccountName = user.SamAccountName,
DisplayName = user.DisplayName,
//Title = user.Title //Won't work, no Title property
});
}
return users;
}
}
这有效,但只返回属性的一小部分。FindOne(( 可以,但是如果我使用 FindOne((,我将无法搜索部分用户名,例如返回"John Smith"和"James Smoth"的"jsm"。
简短的回答是你可以这样做:
foreach (var user in principalSearcher.FindAll())
{
var userDe = (DirectoryEntry) user.GetUnderlyingObject();
users.Add(new ADUser
{
SamAccountName = user.SamAccountName,
DisplayName = user.DisplayName,
Title = userDe.Properties["title"]?.Value.ToString()
});
}
这是我不再使用 AccountManagement
命名空间的部分原因。它在后台使用DirectoryEntry
并隐藏其复杂性,使基本的事情对你来说更容易,但你仍然必须恢复到直接使用DirectoryEntry
来处理某些事情。而且它实际上比直接使用 DirectoryEntry
/DirectorySearcher
执行得慢。
下面是如何通过 DirectorySearcher
执行相同操作的示例。它有点复杂,但我敢打赌你会发现它执行得更快:
public class ADUser
{
public string SamAccountName { get; set; }
public string DisplayName { get; set; }
public string Title { get; set; }
public IEnumerable<ADUser> Get(string username)
{
var users = new List<ADUser>();
var search = new DirectorySearcher(
new DirectoryEntry("LDAP://domain.com"),
$"(&(objectClass=user)(objectCategory=person)(sAMAccountName={username}))",
new [] { "sAMAccountName", "displayName", "title" } //The attributes you want to see
) {
PageSize = 1000 //If you're expecting more than 1000 results, you need this otherwise you'll only get the first 1000 and it'll stop
};
using (var results = search.FindAll()) {
foreach (SearchResult result in results)
{
users.Add(new ADUser
{
SamAccountName = result.Properties.Contains("sAMAccountName") ? result.Properties["sAMAccountName"][0].ToString() : null,
DisplayName = result.Properties.Contains("displayName") ? result.Properties["displayName"][0].ToString() : null,
Title = result.Properties.Contains("title") ? result.Properties["title"][0].ToString() : null
});
}
}
return users;
}
}