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
Get List of Users From Active Directory In A Given AD Group
提问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.
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();
}
}
}
}