Як я можу отримати список користувачів з активного каталогу?


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 року . Не забувайте перед читанням розблокувати chm-файл на сторінці властивостей Провідника.
OneWorld

Відповіді:


229

Якщо ви новачок у Active Directory, я пропоную вам зрозуміти, як Active Directory спочатку зберігає дані.

Active Directory - це фактично сервер LDAP. Об'єкти, що зберігаються на сервері LDAP, зберігаються ієрархічно. Це дуже схоже на зберігання файлів у вашій файловій системі. Ось чому він отримав ім'я сервера Directory та Active Directory

Контейнери та об'єкти в Active Directory можуть бути визначені a distinguished name. Визначне ім’я так CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com. Як і традиційна реляційна база даних, ви можете запускати запити на сервері LDAP. Це називається LDAP-запитом.

Існує ряд способів запуску LDAP-запиту в .NET. Ви можете використовувати DirectorySearcher від System.DirectoryServicesабо SearchRequest від System.DirectoryServices.Protocol.

Що стосується вашого запитання, оскільки ви просите конкретно знайти головний об’єкт користувача, я думаю, що найінтуїтивнішим способом є використання PrincipalSearcher від System.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 Nameта snнадасть вам Last Name. Про ім’я користувача. Думаю, ви мали на увазі ім’я для входу користувача. Зауважте, що на об’єкті користувача AD є два імені входу. Одне з них - samAccountNameце також ім'я для входу користувача до Windows 2000. userPrincipalNameзазвичай використовується після Windows 2000.


2
Що робити, якщо сервер не містить Domain

Як ви використовуєте той самий код, щоб перелічити користувачів із групи оголошень?
nJoshi

Чи існує спосіб за допомогою цього методу звузити пошук лише до тих, хто знаходиться в каталозі, якому було призначено адресу електронної пошти?
ARidder101

Неважливо, я зрозумів це. Я просто повинен був додати, if (((UserPrincipal)result).EmailAddress != null)перш ніж додати результат до свого списку.
ARidder101

2
А що робити, якщо поточний комп'ютер не належить до домену?
Маркус

23

Якщо ви хочете відфільтрувати активні акаунти, додайте це до коду Харві:

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

після першого використання. Потім додайте

  searcher.QueryFilter = userPrin;

перш ніж знайти всіх. І це має отримати вас активних.


Я не думаю, що вам це потрібно, searcher.QueryFilter = userPrin;оскільки ми вже передаємо головний користувач головному шукачеві при ініціалізації, але в іншому випадку дякую за пораду щодо фільтрації лише активних користувачів!
Андрій

1
Так, Андрій має рацію. Отже, в основному це можна замінити додаванням цієї властивості у друге використання заяви:using (var searcher = new PrincipalSearcher(new UserPrincipal(context){ Enabled = true }))
Марко Йованов

Але я подумав, що ти повинен перевірити, чи Enabledif (userPrincipal.Enabled.HasValue)
маєш

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());
        }
}

Що таке "е", будь ласка?
Фанданго68,

1
Дякую, ніколи цього не помічав. Я його змінив, мав бути "у". Я також додав? 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: LOL, так, це так !!! System.Windows.Forms.MessageBox.Show (ex.Message + ex.StackTrace);
Джолман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.