Bagaimana saya bisa mendapatkan daftar pengguna dari direktori aktif?

109

Bagaimana saya bisa mendapatkan daftar pengguna dari direktori aktif? Apakah ada cara untuk menarik nama pengguna, nama depan, nama belakang? Saya melihat posting serupa di mana ini digunakan:

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

Saya tidak pernah melakukan apa pun dengan direktori aktif jadi saya benar-benar tersesat. Bantuan apa pun akan sangat dihargai!

Mike
sumber
3
Baca artikel MSDN yang sangat baik, Mengelola Prinsip-Prinsip Keamanan Direktori di .NETFramework 3.5 untuk pengenalan yang hebat dalam menggunakan AD dengan .NET 3.5
marc_s
Sepertinya artikel @ marc_s diarsipkan, ini tautan yang diperbarui
jb.
@marc_s Saya ingin sekali membaca Pak, tapi tautannya sudah mati. Saya mencoba blogs.msdn.microsoft.com/msdnmagazine/2008/01/16/… ini tetapi bahkan tautan pada artikel itu mengarah ke halaman genetik untuk majalah microsoft
Malcolm Salvador
1
@ Malky.Kid Saya menemukan jalan ke artikel. Gunakan tautan dari komentar pertama ke pertanyaan ini dan unduh edisi Januari 2008 . Jangan lupa untuk membuka blokir file chm di halaman properti Explorer sebelum membaca.
OneWorld

Jawaban:

229

Jika Anda baru mengenal Active Directory, saya sarankan Anda memahami cara Active Directory menyimpan data terlebih dahulu.

Active Directory sebenarnya adalah server LDAP. Objek yang disimpan di server LDAP disimpan secara hierarki. Ini sangat mirip dengan Anda menyimpan file di sistem file Anda. Itu sebabnya ia mendapat nama server Direktori dan Direktori Aktif

Wadah dan objek di Active Directory dapat ditentukan dengan a distinguished name. Nama yang dibedakan adalah seperti ini CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com. Seperti database relasional tradisional, Anda dapat menjalankan kueri pada server LDAP. Ini disebut kueri LDAP.

Ada sejumlah cara untuk menjalankan kueri LDAP di .NET. Anda dapat menggunakan DirectorySearcher dari System.DirectoryServicesatau SearchRequest dari System.DirectoryServices.Protocol.

Untuk pertanyaan Anda, karena Anda meminta untuk menemukan objek utama pengguna secara khusus, menurut saya cara yang paling intuitif adalah dengan menggunakan PrincipalSearcher dari System.DirectoryServices.AccountManagement. Anda dapat dengan mudah menemukan banyak contoh berbeda dari google. Berikut adalah contoh yang melakukan apa yang Anda minta.

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

Perhatikan bahwa pada objek pengguna AD, ada sejumlah atribut. Secara khusus, givenNameakan memberi Anda First Namedan snakan memberi Anda Last Name. Tentang nama pengguna. Saya pikir yang Anda maksud adalah nama logon pengguna. Perhatikan bahwa ada dua nama logon pada objek pengguna AD. Salah satunya samAccountName, yang juga dikenal sebagai nama logon pengguna pra-Windows 2000. userPrincipalNameumumnya digunakan setelah Windows 2000.

Harvey Kwok
sumber
2
Bagaimana jika server tidak berisi Domain
Bagaimana Anda menggunakan kode yang sama untuk membuat daftar pengguna dari grup AD?
nJoshi
Adakah cara menggunakan metode ini untuk mempersempit pencarian hanya pada direktori yang telah diberi alamat email?
ARidder101
Sudahlah, saya menemukan jawabannya. Saya hanya perlu menambahkan if (((UserPrincipal)result).EmailAddress != null)sebelum menambahkan hasilnya ke daftar saya.
ARidder101
2
Dan bagaimana jika komputer saat ini bukan milik domain?
Marcus
23

Jika Anda ingin memfilter akun aktif y, tambahkan ini ke kode Harvey:

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

setelah penggunaan pertama. Lalu tambahkan

  searcher.QueryFilter = userPrin;

sebelum menemukan semua. Dan itu akan membuat Anda menjadi yang aktif.

apereira
sumber
Saya rasa Anda tidak perlu searcher.QueryFilter = userPrin;karena kami telah meneruskan prinsip pengguna ke pencari utama pada inisialisasi, tetapi sebaliknya terima kasih atas tip tentang memfilter pengguna aktif saja!
Andrey
1
Ya, Andrey benar Jadi pada dasarnya ini dapat diganti dengan menambahkan properti ini di pernyataan penggunaan kedua:using (var searcher = new PrincipalSearcher(new UserPrincipal(context){ Enabled = true }))
Marko Jovanov
Tapi saya pikir Anda harus menguji apakah Enabledmemiliki nilai terlebih dahulu:if (userPrincipal.Enabled.HasValue)
JohnB
4

Pastinya kredit diberikan kepada @Harvey Kwok di sini, tetapi saya hanya ingin menambahkan contoh ini karena dalam kasus saya, saya ingin mendapatkan Daftar Prinsip Pengguna yang sebenarnya. Mungkin lebih efisien untuk memfilter kueri ini di muka, tetapi di lingkungan saya yang kecil, lebih mudah untuk menarik semuanya dan kemudian memfilter sesuai kebutuhan nanti dari daftar saya.

Bergantung pada apa yang Anda butuhkan, Anda mungkin tidak perlu mentransmisikan ke DirectoryEntry, tetapi beberapa properti tidak tersedia dari 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());
        }
}
Yordania
sumber
Apa itu 'e' please?
Fandango68
1
Terima kasih, tidak pernah menyadarinya. Saya mengubahnya, seharusnya menjadi "u". Saya juga menambahkan? S untuk menangani nilai null jika properti tersebut hilang.
Jordan
1

Sertakan System.DirectoryServices.dll, kemudian gunakan kode di bawah ini:

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
sumber
1
@ Fandango68: LOL, ya !!! System.Windows.Forms.MessageBox.Show (ex.Message + ex.StackTrace);
Jhollman