Come posso ottenere un elenco di utenti da Active Directory?


109

Come posso ottenere un elenco di utenti da Active Directory? C'è un modo per estrarre nome utente, nome, cognome? Ho visto un post simile in cui è stato utilizzato:

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

Non ho mai fatto nulla con Active Directory, quindi sono completamente perso. Qualsiasi aiuto sarebbe molto apprezzato!


3
Leggi l'eccellente articolo di MSDN sulla gestione delle entità di protezione delle directory in .NET Framework 3.5 per una fantastica introduzione all'uso di AD con .NET 3.5
marc_s

Sembra che l'articolo di @ marc_s sia stato archiviato, ecco un collegamento aggiornato
jb.

@marc_s Mi piacerebbe leggere signore, ma il collegamento è morto. Ho provato questo blogs.msdn.microsoft.com/msdnmagazine/2008/01/16/… ma anche i link su quell'articolo portano a una pagina genetica per la rivista microsoft
Malcolm Salvador

1
@ Malky.Kid Ho trovato la mia strada per l'articolo. Usa il link del primo commento a questa domanda e scarica il numero di gennaio 2008 . Non dimenticare di sbloccare il file chm nella pagina delle proprietà di Explorer prima di leggere.
OneWorld

Risposte:


229

Se sei nuovo in Active Directory, ti suggerisco di capire come Active Directory memorizza prima i dati.

Active Directory è in realtà un server LDAP. Gli oggetti archiviati nel server LDAP vengono archiviati gerarchicamente. È molto simile a quando archivi i tuoi file nel tuo file system. Ecco perché ha ottenuto il nome Directory server e Active Directory

I contenitori e gli oggetti su Active Directory possono essere specificati da un file distinguished name. Il nome distinto è così CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com. Come un database relazionale tradizionale, puoi eseguire query su un server LDAP. Si chiama query LDAP.

Esistono diversi modi per eseguire una query LDAP in .NET. È possibile utilizzare DirectorySearcher da System.DirectoryServiceso SearchRequest da System.DirectoryServices.Protocol.

Per la tua domanda, dal momento che stai chiedendo di trovare specificamente l'oggetto principale dell'utente, penso che il modo più intuitivo sia usare PrincipalSearcher da System.DirectoryServices.AccountManagement. Puoi facilmente trovare molti esempi diversi da google. Ecco un esempio che sta facendo esattamente quello che stai chiedendo.

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

Notare che sull'oggetto utente AD sono presenti numerosi attributi. In particolare, givenNameti darà il First Namee snti darà il Last Name. Informazioni sul nome utente. Penso che intendessi il nome di accesso dell'utente. Notare che esistono due nomi di accesso sull'oggetto utente AD. Uno è samAccountName, noto anche come nome di accesso utente precedente a Windows 2000. userPrincipalNameviene generalmente utilizzato dopo Windows 2000.


2
Cosa succede se il server non contiene il dominio

Come si utilizza lo stesso codice per elencare gli utenti di un gruppo AD?
nJoshi

Esiste un modo utilizzando questo metodo per restringere la ricerca solo a quelli nella directory a cui è stato assegnato un indirizzo e-mail?
ARidder101

Non importa, l'ho capito. Dovevo solo aggiungere if (((UserPrincipal)result).EmailAddress != null)prima di aggiungere il risultato alla mia lista.
ARidder101

2
E se il computer corrente non appartiene al dominio?
Marcus

23

Se vuoi filtrare gli account attivi, aggiungilo al codice di Harvey:

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

dopo il primo utilizzo. Poi aggiungi

  searcher.QueryFilter = userPrin;

prima di trovare tutto. E questo dovrebbe farti diventare quelli attivi.


Non penso che sia necessario searcher.QueryFilter = userPrin;poiché passiamo già l'entità utente al ricercatore principale durante l'inizializzazione, ma per il resto grazie per il suggerimento sul filtraggio solo degli utenti attivi!
Andrey

1
Sì, Andrey ha ragione Quindi fondamentalmente questo potrebbe essere sostituito con l'aggiunta di questa proprietà nella seconda istruzione using:using (var searcher = new PrincipalSearcher(new UserPrincipal(context){ Enabled = true }))
Marko Jovanov

Ma ho pensato che dovessi prima verificare se Enabledavesse un valore:if (userPrincipal.Enabled.HasValue)
JohnB

4

Certamente il merito va a @Harvey Kwok qui, ma volevo solo aggiungere questo esempio perché nel mio caso volevo ottenere un elenco effettivo di UserPrincipals. Probabilmente è più efficiente filtrare questa query in anticipo, ma nel mio piccolo ambiente è più semplice estrarre tutto e quindi filtrare secondo necessità in seguito dal mio elenco.

A seconda di ciò di cui hai bisogno, potrebbe non essere necessario eseguire il cast a DirectoryEntry, ma alcune proprietà non sono disponibili da 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());
        }
}

Che cos'è "e" per favore?
Fandango68

1
Grazie, non l'ho mai notato. L'ho cambiato, avrei dovuto essere "u". Ho anche aggiunto? S per gestire i valori nulli se la proprietà è mancante.
Jordan

1

Includere System.DirectoryServices.dll, quindi utilizzare il codice seguente:

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, sì lo è !!! System.Windows.Forms.MessageBox.Show (ex.Message + ex.StackTrace);
Jhollman
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.