如何从活动目录中获取用户列表?


109

如何从活动目录中获取用户列表?有没有办法提取用户名,名字,姓氏?我看到了一个类似的帖子,其中使用了它:

 PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN");

我从来没有对活动目录做过任何事情,所以我完全迷路了。任何帮助将不胜感激!


3
阅读出色的MSDN文章.NET Framework 3.5中的管理目录安全性主体”,以获取有关将AD与.NET 3.5结合使用的精彩介绍
marc_s

看起来@marc_s的文章已存档,这是更新的链接
jb。

@marc_s我很想读先生,但是链接已经死了。我尝试了这个blogs.msdn.microsoft.com/msdnmagazine/2008/01/16/…但是,即使该文章上的链接也指向了Microsoft杂志的基因页面
Malcolm Salvador

1
@ Malky.Kid我找到了通往这篇文章的方式。使用此问题的第一条评论链接,并下载2008年1月的版本。阅读之前,请不要忘记在资源管理器属性页中取消阻止chm文件。
OneWorld '18

Answers:


229

如果您不熟悉Active Directory,建议您先了解Active Directory如何存储数据。

Active Directory实际上是LDAP服务器。LDAP服务器中存储的对象是分层存储的。这与将文件存储在文件系统中非常相似。这就是为什么它得名目录服务器和Active Directory

Active Directory上的容器和对象可以通过来指定distinguished name。专有名称就是这样CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com。像传统的关系数据库一样,您可以对LDAP服务器运行查询。这称为LDAP查询。

有多种方法可以在.NET中运行LDAP查询。您可以使用的DirectorySearcherSystem.DirectoryServicesSearchRequestSystem.DirectoryServices.Protocol

对于你的问题,因为你是问找到用户主体对象而言,我认为最直观的方法是使用PrincipalSearcherSystem.DirectoryServices.AccountManagement。您可以轻松地从Google找到很多不同的示例。这是一个示例,它可以完全满足您的要求。

using (var context = new PrincipalContext(ContextType.Domain, "yourdomain.com"))
{
    using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
            Console.WriteLine("Last Name : " + de.Properties["sn"].Value);
            Console.WriteLine("SAM account name   : " + de.Properties["samAccountName"].Value);
            Console.WriteLine("User principal name: " + de.Properties["userPrincipalName"].Value);
            Console.WriteLine();
        }
    }
}
Console.ReadLine();

请注意,在AD用户对象上,有许多属性。特别是givenName会给您First Namesn会给您Last Name。关于用户名。我认为您的意思是用户登录名。请注意,AD用户对象上有两个登录名。一个是samAccountName,也称为Windows 2000之前的用户登录名。 userPrincipalName通常在Windows 2000之后使用。


2
如果服务器不包含域

您如何使用相同的代码列出AD组中的用户?
nJoshi

有没有办法使用这种方法将搜索范围缩小到仅目录中已分配了电子邮件地址的搜索?
ARidder101 '17

没关系,我知道了。我只需要添加,if (((UserPrincipal)result).EmailAddress != null)然后再将结果添加到列表中即可。
ARidder101 '17

2
如果当前计算机不属于该域怎么办?
Marcus

23

如果要过滤y个活动帐户,请将其添加到Harvey的代码中:

 UserPrincipal userPrin = new UserPrincipal(context);
 userPrin.Enabled = true;

第一次使用后。然后加

  searcher.QueryFilter = userPrin;

在找到所有之前。那应该让您活跃起来。


我认为您不需要,searcher.QueryFilter = userPrin;因为我们已经在初始化时将用户主体传递给主体搜索器,但是除此之外,感谢您仅过滤活动用户的提示!
Andrey

1
是的,Andrey是正确的,因此基本上可以替换为在第二个using语句中添加此属性:using (var searcher = new PrincipalSearcher(new UserPrincipal(context){ Enabled = true }))
Marko Jovanov

但是我认为您必须首先测试是否Enabled具有价值:if (userPrincipal.Enabled.HasValue)
JohnB

4

当然,这归功于@Harvey Kwok,但我只是想添加此示例,因为在我的情况下,我想获取实际的UserPrincipals列表。预先过滤该查询可能更有效,但是在我的小型环境中,将所有内容提取出来,然后根据需要从列表中进行过滤就更容易了。

根据您的需要,可能不需要强制转换为DirectoryEntry,但是UserPrincipal无法提供某些属性。

using (var searcher = new PrincipalSearcher(new UserPrincipal(new PrincipalContext(ContextType.Domain, Environment.UserDomainName))))
{
    List<UserPrincipal> users = searcher.FindAll().Select(u => (UserPrincipal)u).ToList();
    foreach(var u in users)
        {
            DirectoryEntry d = (DirectoryEntry)u.GetUnderlyingObject();
            Console.WriteLine(d.Properties["GivenName"]?.Value?.ToString() + d.Properties["sn"]?.Value?.ToString());
        }
}

请问“ e”是什么?
Fandango68年

1
谢谢,从来没有注意到。我更改了它,应该是“ u”。如果缺少属性,我还添加了?s来处理空值。
约旦

1

包括System.DirectoryServices.dll,然后使用以下代码:

DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName);
string userNames="Users: ";

foreach (DirectoryEntry child in directoryEntry.Children)
{
    if (child.SchemaClassName == "User")
    {
        userNames += child.Name + Environment.NewLine   ;         
    }

}
MessageBox.Show(userNames);

1
@ Fandango68:大声笑,是的!!!System.Windows.Forms.MessageBox.Show(ex.Message + ex.StackTrace);
Jhollman '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.