System.DirectoryServices.AccountManagement 并返回 IEnumerable o



我正在尝试查询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;
    }
}

最新更新