Please note: This is a rewrite of an article I wrote way back in 2007. The original article has been updated with a link to this one.
As per usual I had a situation where I had to do some Active Directory stuff with VB.NET. I had to grab a list of all the users in our AD so that people could select a user and perform functions on them from within a webpage.
Another note: This article is VB.NET-specific. If you’d like to know how to do this using C# please see this post’s “partner” entitled “Follow Up – List active directory users – This time in C#”
Carrying on though, there are a number of ways you can do this but in the .NET Framework they all involve using the System.DirectoryServices namespace. A couple of quick things to be aware of before you try this yourself:
- Before messing with your Active Directory make sure you know what you’re doing and have the permissions of your AD Administrators (if it’s not you!)
- If you are going to use any of the following code from a .NET console application you’ll need to add a reference to System.DirectoryServices in addition to importing the namespace. I wrote a post a while ago about this entitled “Developer Dumbness” – it has the steps you need to add a reference to a .NET console application.
Anyway, the code below is a simple function that queries your Active Directory domain and retrieves all the user objects. This particular example filters out any user account whose “DisplayName” attribute meets the following criteria (the requirements for the app I had to write):
- Has an email address
- Does not contain the “$” symbol
- Does not contain the words “Admin” or “admin”
- Does not contain the words “Test” or “test”
- Does not contain the words “Service” or “service”
- Does not contain the word “System” or “system”
The example code below is a complete Windows console application that does all of the above. It’s important to note that if you’re using this in a production environment you’ll need to make sure the application containing the code has access to the Active Directory, usually using .NET impersonation – this is beyond the scope of this post.
List Active Directory Users in VB.NET:
Imports System Imports System.Collections.Generic Imports System.DirectoryServices Module ListAdUsers Sub Main(ByVal ParamArray Args() As String) Console.Clear() Dim userList As List(Of String) = New List(Of String) Dim badEntries As Integer = 0 Dim domainName As String = String.Empty If (Args.Length > 0) Then domainName = Args(0) Else Console.Write(String.Format("{0}Please enter your Active Directory domain name: ", vbCrLf)) domainName = Console.ReadLine() End If Console.Write(String.Format("{0}Attempting to build user list for {1} ...{0}{0}", vbCrLf, domainName)) Try If Not String.IsNullOrEmpty(domainName) Then Dim myDirectoryEntry As DirectoryEntry = New DirectoryEntry(String.Format("LDAP://{0}", domainName)) Dim mySearcher As DirectorySearcher = New DirectorySearcher(myDirectoryEntry) Dim mySort As SortOption = New SortOption("sn", SortDirection.Ascending) mySearcher.Filter = ("(objectClass=user)") mySearcher.Sort = mySort For Each resEnt As SearchResult In mySearcher.FindAll() Try If Not String.IsNullOrEmpty(resEnt.Properties("Mail")(0).ToString()) _ AndAlso System.Text.RegularExpressions.Regex.IsMatch(resEnt.Properties("DisplayName")(0).ToString(), " |admin|test|service|system|[$]", System.Text.RegularExpressions.RegexOptions.IgnoreCase) Then Dim space As Integer = resEnt.Properties("DisplayName")(0).ToString().IndexOf(" ") Dim formattedName As String = String.Format("{0}{1}{2}", _ resEnt.Properties("DisplayName")(0).ToString().Substring(space).PadRight(25), _ resEnt.Properties("DisplayName")(0).ToString().Substring(0, space).PadRight(15), _ resEnt.Properties("Mail")(0).ToString() _ ) userList.Add(formattedName) End If Catch badEntries = badEntries + 1 End Try Next If (userList.Count > 0) Then Console.WriteLine(String.Format("=========== Listing of users in the {0} domain{1}", domainName, vbCrLf)) Console.WriteLine(String.Format("{0}{1}{2}{3}", "Surname".PadRight(25), "First Name".PadRight(15), "Email Address", vbCrLf)) For i = 0 To userList.Count - 1 Console.WriteLine(userList(i).ToString()) Next Console.WriteLine(String.Format("{0}=========== {1} users found in the {2} domain", vbCrLf, userList.Count.ToString(), domainName)) Else Console.WriteLine(String.Format("{0}=========== 0 users found in the {1} domain", vbCrLf, userList.Count.ToString())) End If Console.WriteLine(String.Format("=========== {0} objects could not be read", badEntries.ToString())) Console.WriteLine("=========== End of Listing") Else Console.WriteLine("Please enter a domain name next time!") End If Catch ex As Exception ' in a production app you wouldn't show the user the exception details Console.Write(String.Format("A critical error occurred.{0}Details: {1}", vbCrLf, ex.Message.ToString())) End Try End Sub End Module
There are a HEAP of attributes you can use instead of “sn” in the sample above. Personally I use ADSIEDIT.MSC to look at all the possible attributes but you’ll need domain administrative access to run that. Here are a couple of useful ones though …
- company
- department
- description
- displayName
- manager
- name
- givenName
- sAMAccountName
Hope that helps someone! 🙂