Wie kann ich eine Liste der Benutzer aus Active Directory abrufen?

109

Wie kann ich eine Liste der Benutzer aus Active Directory abrufen? Gibt es eine Möglichkeit, Benutzername, Vorname, Nachname abzurufen? Ich habe einen ähnlichen Beitrag gesehen, in dem dieser verwendet wurde:

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

Ich habe noch nie etwas mit Active Directory gemacht, daher bin ich völlig verloren. Jede Hilfe wäre sehr dankbar!

Mike
quelle
3
Lesen Sie den hervorragenden MSDN-Artikel Verwalten von Verzeichnissicherheitsprinzipalen in .NET Framework 3.5, um eine großartige Einführung in die Verwendung von AD mit .NET 3.5 zu erhalten
marc_s
Der Artikel von @ marc_s wurde anscheinend archiviert. Hier ist ein aktualisierter Link
jb.
@marc_s Ich würde gerne Sir lesen, aber der Link ist tot. Ich habe versucht, diese blogs.msdn.microsoft.com/msdnmagazine/2008/01/16/…, aber selbst die Links zu diesem Artikel führen zu einer genetischen Seite für Microsoft Magazine
Malcolm Salvador
1
@ Malky.Kid Ich habe den Weg zum Artikel gefunden. Verwenden Sie den Link des ersten Kommentars zu dieser Frage und laden Sie die Januar-Ausgabe 2008 herunter . Vergessen Sie nicht, die chm-Datei auf der Explorer-Eigenschaftenseite zu entsperren, bevor Sie sie lesen.
OneWorld

Antworten:

229

Wenn Sie mit Active Directory noch nicht vertraut sind, sollten Sie zunächst verstehen, wie Active Directory Daten speichert.

Active Directory ist eigentlich ein LDAP-Server. Auf dem LDAP-Server gespeicherte Objekte werden hierarchisch gespeichert. Es ist sehr ähnlich, wie Sie Ihre Dateien in Ihrem Dateisystem speichern. Deshalb erhielt es den Namen Directory Server und Active Directory

Die Container und Objekte in Active Directory können durch a angegeben werden distinguished name. Der definierte Name ist so CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com. Wie bei einer herkömmlichen relationalen Datenbank können Sie Abfragen für einen LDAP-Server ausführen. Es heißt LDAP-Abfrage.

Es gibt verschiedene Möglichkeiten, eine LDAP-Abfrage in .NET auszuführen. Sie können DirectorySearcher von System.DirectoryServicesoder SearchRequest von verwenden System.DirectoryServices.Protocol.

Für Ihre Frage ist es meiner Meinung nach am intuitivsten, PrincipalSearcher von zu verwenden, da Sie speziell nach dem Hauptobjekt des Benutzers suchen System.DirectoryServices.AccountManagement. Sie können leicht viele verschiedene Beispiele von Google finden. Hier ist ein Beispiel, das genau das tut, wonach Sie fragen.

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

Beachten Sie, dass das AD-Benutzerobjekt eine Reihe von Attributen enthält. Insbesondere givenNamewird Ihnen das geben First Nameund snwird Ihnen das geben Last Name. Über den Benutzernamen. Ich denke, Sie meinten den Benutzernamen. Beachten Sie, dass das AD-Benutzerobjekt zwei Anmeldenamen enthält. Eine davon ist samAccountName, die auch als Anmeldename vor Windows 2000 bezeichnet wird. userPrincipalNamewird in der Regel nach Windows 2000 verwendet.

Harvey Kwok
quelle
2
Was ist, wenn der Server keine Domain enthält
Wie verwenden Sie denselben Code, um Benutzer aus einer AD-Gruppe aufzulisten?
Joshi
Gibt es eine Möglichkeit, mit dieser Methode die Suche auf diejenigen im Verzeichnis zu beschränken, denen eine E-Mail-Adresse zugewiesen wurde?
ARidder101
Egal, ich habe es herausgefunden. Ich musste nur hinzufügen, if (((UserPrincipal)result).EmailAddress != null)bevor ich das Ergebnis zu meiner Liste hinzufügte.
ARidder101
2
Und was ist, wenn der aktuelle Computer nicht zur Domäne gehört?
Marcus
23

Wenn Sie Ihre aktiven Konten filtern möchten, fügen Sie dies zu Harveys Code hinzu:

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

nach dem ersten Gebrauch. Dann füge hinzu

  searcher.QueryFilter = userPrin;

vor dem alles finden. Und das sollte dir die aktiven bringen.

Apereira
quelle
Ich glaube nicht, dass Sie dies benötigen, searcher.QueryFilter = userPrin;da wir das Benutzerprinzipal bereits bei der Initialisierung an den Prinzipalsucher übergeben, aber ansonsten vielen Dank für den Tipp, nur aktive Benutzer zu filtern!
Andrey
1
Ja, Andrey hat recht. Im Grunde könnte dies durch das Hinzufügen dieser Eigenschaft in der zweiten using-Anweisung ersetzt werden:using (var searcher = new PrincipalSearcher(new UserPrincipal(context){ Enabled = true }))
Marko Jovanov
Aber ich dachte, Sie Enabledif (userPrincipal.Enabled.HasValue)
müssten
4

Sicherlich geht der Kredit hier an @Harvey Kwok, aber ich wollte nur dieses Beispiel hinzufügen, weil ich in meinem Fall eine aktuelle Liste der UserPrincipals erhalten wollte. Es ist wahrscheinlich effizienter, diese Abfrage im Voraus zu filtern, aber in meiner kleinen Umgebung ist es einfacher, alles abzurufen und später nach Bedarf aus meiner Liste zu filtern.

Je nachdem, was Sie benötigen, müssen Sie möglicherweise nicht in DirectoryEntry umwandeln, aber einige Eigenschaften sind in UserPrincipal nicht verfügbar.

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());
        }
}
Jordanien
quelle
Was ist 'e' bitte?
Fandango68
1
Danke, habe das nie bemerkt. Ich habe es geändert, sollte "u" sein. Ich habe auch? S hinzugefügt, um Nullwerte zu behandeln, wenn die Eigenschaft fehlt.
Jordanien
1

Fügen Sie die System.DirectoryServices.dll hinzu und verwenden Sie den folgenden Code:

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);
FreeAsInBeer
quelle
1
@ Fandango68: LOL, ja das ist es !!! System.Windows.Forms.MessageBox.Show (ex.Message + ex.StackTrace);
Jhollman