C# 从给定 AD 组中的 Active Directory 获取用户列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/513124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:19:31  来源:igfitidea点击:

Get List of Users From Active Directory In A Given AD Group

c#active-directory

提问by wcm

I have code that searches for all users in a department:

我有搜索部门中所有用户的代码:

string Department = "Billing";
DirectorySearcher LdapSearcher = new DirectorySearcher();
LdapSearcher.PropertiesToLoad.Add("displayName");
LdapSearcher.PropertiesToLoad.Add("cn");
LdapSearcher.PropertiesToLoad.Add("department");
LdapSearcher.PropertiesToLoad.Add("title");
LdapSearcher.PropertiesToLoad.Add("memberOf");
LdapSearcher.Filter = string.Format("(&(objectClass=user)(department={0}))", Department);
SearchResultCollection src = LdapSearcher.FindAll();

What would the filter need to look like if I only wanted everyone in the "Manager Read Only" AD Group?

如果我只需要“Manager Read Only” AD 组中的每个人,过滤器应该是什么样子的?

Am I going about this all wrong?

我在这一切都错了吗?

采纳答案by Dscoduc

Looking at your search I have a couple of points for you. First, the search uses objectClass (non-indexed) instead of objectCategory (indexed). Huge performance issue with that query. You would most always want to combine the two together depending on what you are trying to retrieve:

看看你的搜索,我有几点要给你。首先,搜索使用 objectClass(非索引)而不是 objectCategory(索引)。该查询存在巨大的性能问题。根据您要检索的内容,您总是希望将两者结合在一起:

(&(objectCategory=person)(objectClass=user)) = All users (no contacts)
(&(objectCategory=person)(objectClass=contact)) = All contacts (no users)
(&(objectCategory=person)) = All users and contacts

As for looking up the users in a group you can enumerate the list of member objects of the specific group. In the member attribute of the group object is the distinguishedName of each user.

至于查找组中的用户,您可以枚举特定组的成员对象列表。在组对象的成员属性中是每个用户的distinguishedName。

This article describes enumerating members of a group...

本文介绍了枚举组的成员...

Don't forget that you may have to handle nested groups of the parent group, as there isn't a default way to handle this with LDAP queries. For that you may need to evaluate if the member object is a group and then get the member attribute for that child group.

不要忘记您可能必须处理父组的嵌套组,因为没有默认的方式来处理 LDAP 查询。为此,您可能需要评估成员对象是否为组,然后获取该子组的成员属性。

Lastly, you should get in the habit of specifying a dns prefix to your query.

最后,您应该养成为查询指定 dns 前缀的习惯。

Without DNS prefix:

没有 DNS 前缀:

LDAP://ou=ouname,dc=domain,dc=com

With DNS prefix (all three work):

使用 DNS 前缀(所有三个都有效):

LDAP://servername/ou=ouname,dc=domain,dc=com
LDAP://servername.domain.com/ou=ouname,dc=domain,dc=com
LDAP://domain.com/ou=ouname,dc=domain,dc=com

A single domain won't cause you much issue but when you try and run a search in a multiple domain environment you will get bitten without this addition. Hope this helps move you closer to your goal.

单个域不会给您带来太多问题,但是当您尝试在多域环境中运行搜索时,如果没有此添加,您将被咬。希望这有助于让你更接近你的目标。

回答by nzpcmad

I've always found Howto: (Almost) Everything In Active Directory via C#helps for most AD questions.

我总是发现Howto: (Almost) Everything In Active Directory via C#对大多数 AD 问题都有帮助。

回答by Rob McCready

If you know the AD path to the group already it would probably be easier to open a DirectoryEntry on that, then do a DirectorySearcher from there.

如果您已经知道该组的 AD 路径,那么在其上打开 DirectoryEntry 可能会更容易,然后从那里执行 DirectorySearcher。

using (DirectoryEntry de = new DirectoryEntry("LDAP://somedomain/CN=FooBar"))
{
   DirectorySearcher search = new DirectorySearcher(de, ("(objectClass=user)"));
}

There is also a flag on the Searcher for whether to drill down to sub containers, I forget the name off hand.

搜索器上还有一个标志,用于是否深入到子容器,我忘记了名称。

回答by Petr

I use following code (from http://blogs.technet.com/b/brad_rutkowski/archive/2008/04/15/c-getting-members-of-a-group-the-easy-way-with-net-3-5-discussion-groups-nested-recursive-security-groups-etc.aspx) it works fine.

我使用以下代码(来自http://blogs.technet.com/b/brad_rutkowski/archive/2008/04/15/c-getting-members-of-a-group-the-easy-way-with-net- 3-5-discussion-groups-nested-recursive-security-groups-etc.aspx)它工作正常。

IList<string> getMembers(string domainName, string groupName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
        GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, groupName);

        if (grp == null) { 
            throw new ApplicationException("We did not find that group in that domain, perhaps the group resides in a different domain?");
        }

        IList<string> members = new List<String>();

        foreach (Principal p in grp.GetMembers(true))
        {
            members.Add(p.Name); //You can add more attributes, samaccountname, UPN, DN, object type, etc... 
        }
        grp.Dispose();
        ctx.Dispose();

        return members;
    }

回答by Howard Rothenburg

    //Search for Group and list group members

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.DirectoryServices.AccountManagement;

namespace ExportActiveDirectoryGroupsUsers
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null)
            {
                Console.WriteLine("args is null, useage: ExportActiveDirectoryGroupsUsers OutputPath"); // Check for null array
            }
            else
            {
                Console.Write("args length is ");
                Console.WriteLine(args.Length); // Write array length
                for (int i = 0; i < args.Length; i++) // Loop through array
                {
                    string argument = args[i];
                    Console.Write("args index ");
                    Console.Write(i); // Write index
                    Console.Write(" is [");
                    Console.Write(argument); // Write string
                    Console.WriteLine("]");
                }
                try
                {
                    using (var ServerContext = new PrincipalContext(ContextType.Domain, ServerAddress, Username, Password))
                    {
                        /// define a "query-by-example" principal - here, we search for a GroupPrincipal 
                        GroupPrincipal qbeGroup = new GroupPrincipal(ServerContext, args[0]);

                        // create your principal searcher passing in the QBE principal    
                        PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);

                        // find all matches
                        foreach (var found in srch.FindAll())
                        {
                            GroupPrincipal foundGroup = found as GroupPrincipal;

                            if (foundGroup != null)
                            {
                                // iterate over members
                                foreach (Principal p in foundGroup.GetMembers())
                                {
                                    Console.WriteLine("{0}|{1}", foundGroup.Name, p.DisplayName);
                                    // do whatever you need to do to those members
                                }
                            }

                        }
                    }
                    //Console.WriteLine("end");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Something wrong happened in the AD Query module: " + ex.ToString());
                }
                Console.ReadLine();
            }
        }
    }
}