Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Working with Active Directory in VB.NET

4.80/5 (41 votes)
3 Aug 2007CPOL8 min read 1   25.9K  
This article explains how to perform tasks within the Active Directory in a Windows 2000+ network.

Introduction

This article discusses working within the Active Directory (AD) using VB.NET, how to query the AD, query groups, members, adding users, suspending users, and changing user passwords. The Active Directory is the Windows directory service that provides a unified view of the entire network. Working with the Active Directory is a lot like working with a database, you write queries based on the information you want to retrieve.

There are three interfaces for accessing the Active Directory:

  1. LDAP: The Lightweight Directory Access Protocol (LDAP) is the service protocol that runs on a layer above the TCP/IP layer (or stack) and provides an interface for accessing, searching, and modifying Internet Directories, and is based on a client-server model.
  2. ADSI: The Active Directory Services Interface (ADSI) is a set of COM components (or Interfaces) designed to access the directory services from different network providers in a network setup; it is designed to provide a single, central interface for accessing and managing network resources.
  3. System.DirectoryServices: The System.DirectoryServices namespace built into the .NET Framework is designed to provide programming access to LDAP directories (Active Directory), and is built on the ASDI API.

Background

Recently, at work, I was tasked with creating a security system for the application I currently program. I took this a step further, and wanted to ensure that in the event the application was ever taken off-site, that it couldn't run; this is when I came up with the idea of basing my security on the Active Directory of the company network. This would prevent an individual from taking the application off-site and attempting to use it, either for malicious purposes or to just "play" around with it. This also seemed to be the most secure way as only a select group of people actually have the permissions to alter the Active Directory in any way. Though there is a ton of built-in functionality in the .NET Framework for working with the Active Directory, I decided to create my own object, a wrapper around the System.DirectoryServices namespace in .NET.

The employees who use this application are all in a single department. They, in turn, have their own table in the database holding specific information about the user, i.e., access level, queue, and such. When we first launched this application, the security was based on the user's access level in the database. This determined what the user had access to. When the application launched, it checked the name the user was logged in as:

VB
Environment.UserName.ToString

It then split the user name (at my company, your username is FirstName.LastName) to return the first and last name, and queried the aforementioned table to retrieve the user's access level based on the first and last name retrieved earlier. I wanted to keep the access level security as this ensured people didn't have access to areas of the application they shouldn't have, so I added a new column to the user table to hold their AD login (data type SysUser). From there, I would use Environment.UserName.ToString to once again retrieve the username they are logged in with. With this, I would retrieve their LoginName from the users table, and query the Active Directory to ensure this is a valid network account and they have permissions to be using this application.

Working on this AD security, I discovered the true power of the System.DirectoryServices namespace; with it you can:

  1. Add a new user to the network
  2. Suspend a user's account
  3. Enable a user's account
  4. Reset a user's password
  5. Update a user account
  6. Add a user to a specific group
  7. Remove a user from a group
  8. Retrieve the list of all groups a user is a member of
  9. Retrieve all computers connected to the network
  10. Determine if a user's account is disabled
  11. Check if a user account is active (perform a basic login)

and so much more. In this article, I will walk you through connecting to an Active Directory, searching for users in the Active Directory, disabling a user's account, resetting a user's password, setting up a mailbox for a new user, displaying all computers on the network, and adding a user to a specific group in the Active Directory.

Using the code

I will get this helper out of the way first, many of the procedures/functions will be calling this helper. The job of this helper is simply to set the properties of a user's AD account. This saves time and code when properties need to either be set or altered. This helper searches the provided property to see if it already exists in the user's account; if it doesn't, then it adds and sets the value; if it already exists, it updates the property's value:

VB
''' <summary>
''' Helper method that sets properties for AD users.
''' </summary>
''' <param name="de">DirectoryEntry to use</param>
''' <param name="pName">Property name to set</param>
''' <param name="pValue">Value of property to set</param>
Public Shared Sub SetADProperty(ByVal de As DirectoryEntry, _
ByVal pName As String, ByVal pValue As String)
    'First make sure the property value isnt "nothing"
    If Not pValue Is Nothing Then
        'Check to see if the DirectoryEntry contains this property already
        If de.Properties.Contains(pName) Then 'The DE contains this property
            'Update the properties value
            de.Properties(pName)(0) = pValue
        Else    'Property doesnt exist
            'Add the property and set it's value
            de.Properties(pName).Add(pValue)
        End If
    End If
End Sub

The first thing to do when working with the Active Directory is to create a connection to the Active Directory:

VB
''' <summary>
''' Method used to create an entry to the AD.
''' Replace the path, username, and password with the ones specific to you 
'''and your network. 
'''Hardcoding a username & password can be viewed as a security risk
'''    so you may want to store this in an encrypted file.
''' </summary>
''' <returns> A DirectoryEntry </returns>
Public Shared Function GetDirectoryEntry() As DirectoryEntry
    Dim dirEntry As DirectoryEntry = New DirectoryEntry()
    dirEntry.Path = "LDAP://192.168.1.1/CN=Users;DC=Yourdomain"
    dirEntry.Username = "yourdomain\sampleuser"
    dirEntry.Password = "samplepassword"
    Return dirEntry
End Function

As stated above, when I added the new column to the users table to hold their AD login (the SysUser data type built into SQL2000/2005), this data type holds the value in the format DOMAIN\USERNAME. When searching the Active Directory for a specific user, you need to strip the "DOMAIN\" off, so I created the following function to do this for me:

VB
''' <summary>
''' Function to extract just the login from the provided string 
''' (given in the format DOMAIN\USERNAME)
''' </summary>
''' <param name="path">Full AD login of the user</param>
''' <returns>The login with the "DOMAIN\" stripped</returns>
Public Function ExtractUserName(ByVal path As String) As String
    Dim userPath As String() = path.Split(New Char() {"\"c})
    Return userPath((userPath.Length - 1))
End Function

To search for the provided user in the Active Directory, I created the following function:

VB
''' <summary>
''' Function to search the Active Directory and ensure the Login provided 
''' in Agent Process is a valid one. The search is performed
''' to see if the login provided exists for the first and last name of 
''' the user being queried
''' </summary>
''' <param name="loginName">Login of the associate to search for</param>
''' <param name="givenName">First name fo the associate being added</param>
''' <param name="surName">Last name of the associate being added</param>
''' <returns>True or False depending if the login provided is a valid one</returns>
Public Function IsValidADLogin(ByVal loginName As String, _
       ByVal givenName As String, ByVal surName As String) As Boolean
    Try
        Dim search As New DirectorySearcher()
        search.Filter = String.Format("(&(SAMAccountName={0}) & _
                        (givenName={1})(sn={2}))", _
                        ExtractUserName(loginName), givenName, surName)
        search.PropertiesToLoad.Add("cn")
        search.PropertiesToLoad.Add("SAMAccountName")   'Users login name
        search.PropertiesToLoad.Add("givenName")    'Users first name
        search.PropertiesToLoad.Add("sn")   'Users last name
        'Use the .FindOne() Method to stop as soon as a match is found
        Dim result As SearchResult = search.FindOne()
        If result Is Nothing Then
            Return False
        Else
            Return True
        End If
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Active Directory Error", & _
MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)
    End Try
End Function

With this function, if the selected user is found, then True is returned, else False is returned, letting the programmer know that this isn't a valid user in the Active Directory. As stated earlier, there are many things you can do when accessing the Active Directory; I will now walk you through just a sample of the things possible with the System.DirectoryServices namespace.

The first example will be creating a new AD user; in order to use this functionality, you must have an account that has the proper permissions to add a user. (All accounts have access to search the Active Directory, only members of the Administrator Group can perform many of the functions, including creating a new AD user.) The easiest way to do this is to delegate the permissions of a user account with DomainAdmin permissions to the thread that is running the program. The following code will take care of this for you:

VB
'' <summary>
''' Establish identity (principal) and culture for a thread.
''' </summary>
Public Shared Sub SetCultureAndIdentity()
    AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
    Dim principal As WindowsPrincipal = CType(Thread.CurrentPrincipal, WindowsPrincipal)
    Dim identity As WindowsIdentity = CType(principal.Identity, WindowsIdentity)
    System.Threading.Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
End Sub

1. Creating a new Active Directory user account

There are four procedures required to perform this. The first procedure, CreateADAccount, is the procedure that actually creates the new user. It relies on three other procedures: SetPassword is used to set the password of the new user, EnableAccount is used to enable the new account, and AddUserToGroup is used to add the new user to the specified Active Directory Group.

First, let's look at the CreateADAccount procedure:

VB
''' <summary>
''' Procedure to create a new Active Directory account
''' </summary>
''' <param name="sUserName">Username for the new account</param>
''' <param name="sPassword">Password for the new account</param>
''' <param name="sFirstName">First name of the user</param>
''' <param name="sLastName">Last name of the user</param>
''' <param name="sGroupName">Group to add the user to</param>
''' <remarks></remarks>
Public Sub CreateAdAccount(ByVal sUserName As String, _
       ByVal sPassword As String, _
       ByVal sFirstName As String, ByVal sLastName As String, _
       ByVal sGroupName As String)
    Dim catalog As Catalog = New Catalog()
    Dim dirEntry As New DirectoryEntry()
    ' 1. Create user account
    Dim adUsers As DirectoryEntries = dirEntry.Children
    Dim newUser As DirectoryEntry = adUsers.Add("CN=" & sUserName, "user")
    ' 2. Set properties
    SetProperty(newUser, "givenname", sFirstName)
    SetProperty(newUser, "sn", sLastName)
    SetProperty(newUser, "SAMAccountName", sUserName)
    SetProperty(newUser, "userPrincipalName", sUserName)
    newUser.CommitChanges()
    ' 3. Set the password
    SetPassword(newUser, sPassword)
    ' 5. Add the user to the specified group
    AddUserToGroup(dirEntry, newUser, sGroupName)
    ' 6. Enable the account
    EnableAccount(newUser)
    ' 7. Close & clean-up
    newUser.Close()
    dirEntry.Close()
End Sub

The three highlighted lines at the end of the procedure are referring to the three additional procedures mentioned above, the first being SetPassword:

VB
'' <summary>
''' Method to set a user's password
''' <param name="dEntry">DirectoryEntry to use</param>
''' <param name="sPassword">Password for the new user</param>
Private Shared Sub SetPassword(ByVal dEntry As DirectoryEntry, _
ByVal sPassword As String)
    Dim oPassword As Object() = New Object() {sPassword}
    Dim ret As Object = dEntry.Invoke("SetPassword", oPassword)
    dEntry.CommitChanges()
End Sub

The second procedure is the EnableAccount, which is responsible for enabling the new account so the user can use it:

VB
''' <summary>
''' Method to enable a user account in the AD.
''' </summary>
''' <param name="de"></param>
Private Shared Sub EnableAccount(ByVal de As DirectoryEntry)
    'UF_DONT_EXPIRE_PASSWD 0x10000
    Dim exp As Integer = CInt(de.Properties("userAccountControl").Value)
    de.Properties("userAccountControl").Value = exp Or &H1
    de.CommitChanges()
    'UF_ACCOUNTDISABLE 0x0002
    Dim val As Integer = CInt(de.Properties("userAccountControl").Value)
    de.Properties("userAccountControl").Value = val And Not &H2
    de.CommitChanges()
End Sub

The third and final procedure is the AddUserToGroup, which adds the new user to the specified Active Directory Group:

VB
'' <summary>
''' Method to add a user to a group
''' </summary>
''' <param name="de">DirectoryEntry to use</param>
''' <param name="deUser">User DirectoryEntry to use</param>
''' <param name="GroupName">Group Name to add user to</param>
Public Shared Sub AddUserToGroup(ByVal de As DirectoryEntry, _
ByVal deUser As DirectoryEntry, ByVal GroupName As String)
    Dim deSearch As DirectorySearcher = New DirectorySearcher()
    deSearch.SearchRoot = de
    deSearch.Filter = "(&(objectClass=group) (cn=" & GroupName & "))"
    Dim results As SearchResultCollection = deSearch.FindAll()
    Dim isGroupMember As Boolean = False
    If results.Count > 0 Then
        Dim group As New DirectoryEntry(results(0).Path)
        Dim members As Object = group.Invoke("Members", Nothing)
        For Each member As Object In CType(members, IEnumerable)
            Dim x As DirectoryEntry = New DirectoryEntry(member)
            Dim name As String = x.Name
            If name <> deUser.Name Then
                isGroupMember = False
            Else
                isGroupMember = True
                Exit For
            End If
        Next member
        If (Not isGroupMember) Then
            group.Invoke("Add", New Object() {deUser.Path.ToString()})
        End If
        group.Close()
    End If
    Return
End Sub

2. Disable a user account

With the System.DirectoryServices namespace, you not only can create a new Active Directory user, but can also disable a user's Active Directory account. To disable a user's Active Directory account, use the following procedure:

VB
''' <summary>
''' Method that disables a user account in the AD 
''' and hides user's email from Exchange address lists.
''' </summary>
''' <param name="sLogin">Login of the user to disable</param>
Public Sub DisableAccount(ByVal sLogin As String)
    '   1. Search the Active Directory for the desired user
    Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
    Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
    dirSearcher.Filter = "(&(objectCategory=Person)(objectClass=user) _
(SAMAccountName=" & sLogin & "))"
    dirSearcher.SearchScope = SearchScope.Subtree
    Dim results As SearchResult = dirSearcher.FindOne()
    '   2. Check returned results
    If Not results Is Nothing Then
        '   2a. User was returned
        Dim dirEntryResults As DirectoryEntry = _
                            GetDirectoryEntry(results.Path)
        Dim iVal As Integer = _
            CInt(dirEntryResults.Properties("userAccountControl").Value)
        '   3. Disable the users account
        dirEntryResults.Properties("userAccountControl").Value = iVal Or &H2
        '   4. Hide users email from all Exchange Mailing Lists
        dirEntryResults.Properties("msExchHideFromAddressLists").Value = "TRUE"
        dirEntryResults.CommitChanges()
        dirEntryResults.Close()
    End If
    dirEntry.Close()
End Sub

3. Update/Modify a user's Active Directory account information

With the System.DirectoryServices namespace, you not only can create a new Active Directory user and disable a user's Active Directory account, but can also update/modify a user's Active Directory account properties. The properties in this procedure will differ from the properties in your Active Directory, so you will need access to see what properties are available; the ones I have listed are just a small sample of the possible properties. To update/modify a user's Active Directory account, use the following procedure:

VB
''' <summary>
''' Method that updates user's properties
''' </summary>
''' <param name="userLogin">Login of the user to update</param>
''' <param name="userDepartment">New department of the specified user</param>
''' <param name="userTitle">New title of the specified user</param>
''' <param name="userPhoneExt">New phone extension of the specified user</param>
Public Sub UpdateUserADAccount(ByVal userLogin As String, _
           ByVal userDepartment As String, _
           ByVal userTitle As String, ByVal userPhoneExt As String)
    Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
    Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
    '   1. Search the Active Directory for the speied user
    dirSearcher.Filter = "(&(objectCategory=Person)(objectClass=user) _
         (SAMAccountName=" & userLogin & "))"
    dirSearcher.SearchScope = SearchScope.Subtree
    Dim searchResults As SearchResult = dirSearcher.FindOne()
    If Not searchResults Is Nothing Then
        Dim dirEntryResults As New DirectoryEntry(results.Path)
        'The properties listed here may be different then the 
        'properties in your Active Directory so they may need to be 
        'changed according to your network
        '   2. Set the new property values for the specified user
        SetProperty(dirEntryResults, "department", userDepartment)
        SetProperty(dirEntryResults, "title", userTitle)
        SetProperty(dirEntryResults, "phone", userPhoneExt)
        '   3. Commit the changes
        dirEntryResults.CommitChanges()
        '   4. Close & Cleanup
        dirEntryResults.Close()
    End If
    '   4a. Close & Cleanup
    dirEntry.Close()
End Sub

4. Listing all computers in the Active Directory

Using the System.DirectoryServices namespace in the .NET Framework, you can also create a list of all the computers listed in the Active Directory. When I created this function, I populated a Collection with each computer name, then I could enumerate through the Collection and populate a control (such as ListBox, DataGridView, and such) with the names returned from the Active Directory query. The function used is:

VB
''' <summary>
''' Function to query the Active Directory and return all the computer names 
'''on the network
''' </summary>
''' <returns>A collection populated with all the computer names</returns>
Public Shared Function ListAllADComputers() As Collection
    Dim dirEntry As DirectoryEntry = GetDirectoryEntry()
    Dim pcList As New Collection()
    '   1. Search the Active Directory for all objects with type of computer
    Dim dirSearcher As DirectorySearcher = New DirectorySearcher(dirEntry)
    dirSearcher.Filter = ("(objectClass=computer)")
    '   2. Check the search results
    Dim dirSearchResults As SearchResult
    '   3. Loop through all the computer names returned
    For Each dirSearchResults In dirSearcher.FindAll()
      '   4. Check to ensure the computer name isnt already listed in 
             'the collection
      If Not pcList.Contains(dirSearchResults.GetDirectoryEntry().Name.ToString()) Then
          '   5. Add the computer name to the collection (since 
                 'it dont already exist)
          pcList.Add(dirSearchResults.GetDirectoryEntry().Name.ToString())
      End If
    Next
    '   6. Return the results
    Return pcList
End Function

5. List all groups a user is in

The following function returns a Collection of Groups the user is a member of. I went with the Collection rather than a string concatenated with the Group names, as this way, I can populate a control with the values:

VB
''' <summary>
''' Function to return all the groups the user is a member od
''' </summary>
''' <param name="_path">Path to bind to the AD</param>
''' <param name="username">Username of the user</param>
''' <param name="password">password of the user</param>
Private Function GetGroups(ByVal _path As String, ByVal username As String, _
                 ByVal password As String) As Collection
    Dim Groups As New Collection
    Dim dirEntry As New _
        System.DirectoryServices.DirectoryEntry(_path, username, password)
    Dim dirSearcher As New DirectorySearcher(dirEntry)
    dirSearcher.Filter = String.Format("(sAMAccountName={0}))", username)
    dirSearcher.PropertiesToLoad.Add("memberOf")
    Dim propCount As Integer
    Try
        Dim dirSearchResults As SearchResult = dirSearcher.FindOne()
        propCount = dirSearchResults.Properties("memberOf").Count
        Dim dn As String
        Dim equalsIndex As String
        Dim commaIndex As String
        For i As Integer = 0 To propCount - 1
            dn = dirSearchResults.Properties("memberOf")(i)
            equalsIndex = dn.IndexOf("=", 1)
            commaIndex = dn.IndexOf(",", 1)
            If equalsIndex = -1 Then
                Return Nothing
            End If
            If Not Groups.Contains(dn.Substring((equalsIndex + 1), _
                                  (commaIndex - equalsIndex) - 1)) Then
                Groups.Add(dn.Substring((equalsIndex + 1), & _
                                       (commaIndex - equalsIndex) - 1))
            End If
        Next
    Catch ex As Exception
        If ex.GetType Is GetType(System.NullReferenceException) Then
            MessageBox.Show("Selected user isn't a member of any groups " & _
                            "at this time.", "No groups listed", _
                            MessageBoxButtons.OK, MessageBoxIcon.Error)
            'they are still a good user just does not
            'have a "memberOf" attribute so it errors out.
            'code to do something else here if you want
        Else
            MessageBox.Show(ex.Message.ToString, "Search Error", & _
 MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End Try
    Return Groups
End Function
End Class

6. Determine if a user's account has been disabled

The following function can be used to determine if a selected user's account had been disabled:

VB
''' <summary>
''' This will perfrom a logical operation on the userAccountControl values
''' to see if the user account is enabled or disabled.
''' The flag for determining if the
''' account is active is a bitwise value (decimal =2)
''' </summary>
''' <param name="userAccountControl"></param>
''' <returns></returns>
Public Shared Function IsAccountActive(ByVal userAccountControl As Integer) _
                       As Boolean
    Dim accountDisabled As Integer = & _
        Convert.ToInt32(ADAccountOptions.UF_ACCOUNTDISABLE)
    Dim flagExists As Integer = userAccountControl And accountDisabled
    'if a match is found, then the disabled 
    'flag exists within the control flags
    If flagExists > 0 Then
        Return False
    Else
        Return True
    End If
End Function

7. Remove a user from a specific group

The following function can be used to remove a user from a specific group:

VB
''' <summary>
''' This will perform the removal of a user from the specified group
''' </summary>
''' <param name="UserName">Username of the user to remove</param>
''' <param name="GroupName">Groupname to remove them from</param>
''' <remarks></remarks>
Public Shared Sub RemoveUserFromGroup(ByVal UserName As String, _
                  ByVal GroupName As String)

    Dim Domain As New String("")
    
    'get reference to group
    Domain = "/CN=" + GroupName + ",CN=Users," + GetLDAPDomain()
    Dim oGroup As DirectoryEntry = GetDirectoryObject(Domain)
    
    'get reference to user
    Domain = "/CN=" + UserName + ",CN=Users," + GetLDAPDomain()
    Dim oUser As DirectoryEntry = GetDirectoryObject(Domain)
    
    'Add the user to the group via the invoke method
    oGroup.Invoke("Remove", New Object() {oUser.Path.ToString()})
    
    oGroup.Close()
    oUser.Close()
End Sub

8. Check a user account to see if it's active

The following process does a simulated login to a user's account to see if it's a valid account and if it's active. This method calls other functions to work properly: GetUser and the overrides GetUser, IsUserValid, and IsAccountActive; all of these will be listed here.

VB
 ''' <summary>
''' This method will not actually log a user in, but will perform tests to ensure
''' that the user account exists (matched by both the username and password), and also
''' checks if the account is active.
''' </summary>
''' <param name="UserName"></param>
''' <param name="Password"></param>
Public Shared Function Login(ByVal UserName As String, ByVal Password As String) _
              As ADWrapper.LoginResult
    'first, check if the logon exists based on the username and password
    If IsUserValid(UserName, Password) Then
        Dim dirEntry As DirectoryEntry = GetUser(UserName)
        If Not dirEntry Is Nothing Then
            'convert the accountControl value so that a logical 
            'operation can be performed
            'to check of the Disabled option exists.
            Dim accountControl As Integer = & _
            Convert.ToInt32(dirEntry.Properties("userAccountControl")(0))
            dirEntry.Close()

            'if the disabled item does not exist then the account is active
            If Not IsAccountActive(accountControl) Then
                Return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE
            Else
                Return LoginResult.LOGIN_OK

            End If
        Else
            Return LoginResult.LOGIN_USER_DOESNT_EXIST
        End If
    Else
        Return LoginResult.LOGIN_USER_DOESNT_EXIST
    End If
End Function

GetUser (+Overrides version)

VB
''' <summary>
''' This will return a DirectoryEntry object if the user does exist
''' </summary>
''' <param name="UserName"></param>
''' <returns></returns>
Public Shared Function GetUser(ByVal UserName As String) As DirectoryEntry
    'create an instance of the DirectoryEntry
    Dim dirEntry As DirectoryEntry = GetDirectoryObject("/" + GetLDAPDomain())

    'create instance fo the direcory searcher
    Dim dirSearch As New DirectorySearcher(dirEntry)

    dirSearch.SearchRoot = dirEntry
    'set the search filter
    dirSearch.Filter = "(&(objectCategory=user)(cn=" + UserName + "))"
    'deSearch.SearchScope = SearchScope.Subtree;

    'find the first instance
    Dim searchResults As SearchResult = dirSearch.FindOne()

    'if found then return, otherwise return Null
    If Not searchResults Is Nothing Then
        'de= new DirectoryEntry(results.Path,ADAdminUser, _
             ADAdminPassword,AuthenticationTypes.Secure);
        'if so then return the DirectoryEntry object
        Return searchResults.GetDirectoryEntry()
    Else
        Return Nothing
    End If
End Function


''' <summary>
''' Override method which will perfrom query based on combination of username 
'''and password This is used with the login process to validate the user 
'''credentials and return a user object for further validation. This is 
'''slightly different from the other GetUser... methods as this will use the 
'''UserName and Password supplied as the authentication to check if the user 
'''exists, if so then  the users object will be queried using these 
'''credentials
''' </summary>
''' <param name="UserName"></param>
''' <param name="password"></param>
''' <returns></returns>
Public Shared Function GetUser(ByVal UserName As String, ByVal Password _
                               As String) As DirectoryEntry
    'create an instance of the DirectoryEntry
    Dim dirEntry As DirectoryEntry = GetDirectoryObject(UserName, Password)

    'create instance fo the direcory searcher
    Dim dirSearch As New DirectorySearcher()

    dirSearch.SearchRoot = dirEntry
    'set the search filter
    dirSearch.Filter = "(&(objectClass=user)(cn=" + UserName + "))"
    dirSearch.SearchScope = SearchScope.Subtree

    'set the property to return
    'deSearch.PropertiesToLoad.Add("givenName");

    'find the first instance
    Dim searchResults As SearchResult = dirSearch.FindOne()

    'if a match is found, then create directiry object and return, 
    'otherwise return Null
    If Not searchResults Is Nothing Then
        'create the user object based on the admin priv.
        dirEntry = New DirectoryEntry(searchResults.Path, ADAdminUser, _
                       ADAdminPassword, AuthenticationTypes.Secure)
        Return dirEntry
    Else
        Return Nothing
    End If
End Function

IsUserValid

This procedure will check to make sure it is a valid user account:

VB
''' <summary>
''' This method will attempt to log in a user based on the username and 
''' password
''' to ensure that they have been set up within the Active Directory. 
'''This is the basic UserName, Password
''' check.
''' </summary>
''' <param name="UserName"></param>
''' <param name="Password"></param>
Public Shared Function IsUserValid(ByVal UserName As String, _
                       ByVal Password As String) As Boolean
    Try
        'if the object can be created then return true
        Dim dirUser As DirectoryEntry = GetUser(UserName, Password)
        dirUser.Close()
        Return True
    Catch generatedExceptionName As Exception
        'otherwise return false
        Return False
    End Try
End Function

IsUserActive

This will check to see if it is an active user account:

VB
''' <summary>
''' This will perfrom a logical operation on the userAccountControl values
''' to see if the user account is enabled or disabled. The flag for determining if the
''' account is active is a bitwise value (decimal =2)
''' </summary>
''' <param name="userAccountControl"></param>
''' <returns></returns>
Public Shared Function IsAccountActive(ByVal userAccountControl As Integer) _
                                       As Boolean
    Dim accountDisabled As Integer = _
        Convert.ToInt32(ADAccountOptions.UF_ACCOUNTDISABLE)
    Dim flagExists As Integer = userAccountControl And accountDisabled
    'if a match is found, then the disabled flag exists within the control flags
    If flagExists > 0 Then
        Return False
    Else
        Return True
    End If
End Function

Points of interest

This is really a high level overview of working with the Active Directory in VB.NET. There is more functionality in the wrapper DLL I have for download with this article, such as querying the AD for all active groups, returning all users who are a member of a Group you specify, etc. Working with the Active Directory can be daunting at first, but don't let it scare you off. Once you learn just a few items, it's no more complicated than querying a database for information.

*Special thanks to Erika Ehrli, whose article on VBDotNetHeaven.Com helped me solve some AD logic I struggled with.*

Happy coding!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)