Link to home
Start Free TrialLog in
Avatar of Bhaskar CP
Bhaskar CPFlag for India

asked on

User Search and Disabling Application by Active Directory

I am working on creating a application to search for users with "display name" and loginid
Review the same below and disable the user,move the user to a different ou and modify the description as well.
Achieved:
  Able to search user with login name

*Troubles i am having are:
     ** Unable to make the code so that i can search with Display name
     ** Unable to get the Managers email id of the user
     **Unable to create a plan in which the disabling,moving the user to a different ou can be done.

can someone assist on the same.

Option Explicit On
Imports System.DirectoryServices
Imports System.IO
Imports Microsoft.Win32
Imports System.Drawing
Imports Microsoft.VisualBasic
 
Public Class UTT
 
 
   Private Sub searchbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles searchbtn.Click
        Dim pass1 As String = ""
        Dim pass2 As String = ""
        If samidtxt.Text <> "" Or displaynametxt.Text <> "" Then
            Dim search1 = Len(samidtxt.Text)
            Dim search2 = Len(displaynametxt.Text)
            If search1 <> "0" And search2 = "0" Then pass1 = samidtxt.Text Else 
            If search2 <> "0" And search1 = "0" Then pass1 = displaynametxt.Text
            If pass1 = samidtxt.Text Then pass2 = "1"
            If pass1 = displaynametxt.Text Then pass2 = "2"
 
 
            result_displaynametext.Text = GetFields(pass1, "givenname", pass2)
            result_samidtext.Text = GetFields(pass1, "sAMAccountName", pass2)
            result_desctext.Text = GetFields(pass1, "description", pass2)
            result_emailidtext.Text = GetFields(pass1, "manager", pass2)
            result_isdisabled.Text = GetFields(pass1, "userAccountControl", pass2)
            If result_isdisabled.Text = "514" Then result_isdisabled.Text = "Yes" Else result_isdisabled.Text = "NO"
            If result_isdisabled.Text = "" Then result_isdisabled.Text = ""
            'If result_isdisabled.Text = "NO" Then result_isdisabled.BackColor = Color.Tomato Else 
            If result_isdisabled.Text = "Yes" Then tick.Visible = True Else tick.Visible = False
 
 
 
 
 
 
        End If
    End Sub
 
 
    Public Shared Function GetFields(ByVal UserName As String, ByVal neededvalue As String, ByVal pass2 As Integer) As String
 
        'Const DomainName As String = " schusterna.com"
        Dim DomainName As String = Environment.UserDomainName
        Dim oDirectory As New DirectoryEntry("LDAP://" & DomainName)
        Dim mySearcher As New DirectorySearcher(oDirectory)
        Dim oResult As SearchResult
        Dim sResult As String = ""
        mySearcher.SearchScope = SearchScope.Subtree
        mySearcher.ReferralChasing = ReferralChasingOption.All
        If pass2 = "1" Then
 
            mySearcher.Filter = "(&(objectClass=user)(sAMAccountName=" & UserName & "))"
        Else
            If pass2 = "2" Then
                mySearcher.Filter = "(&(objectClass=user)(name=" & UserName & "))"
            End If
        End If
        Try
            oResult = mySearcher.FindOne
            If Not oResult Is Nothing Then
                sResult = oResult.GetDirectoryEntry.Properties(neededvalue).Value.ToString()
                'Dim desc As String=(mySearcher., neededvalue:="Desc")
 
                
 
            End If
        Catch ex As Exception
            Throw ex
        End Try
 
        oResult = Nothing
        mySearcher.Dispose()
        oDirectory.Dispose()
        Return sResult
    End Function
 
 
 
 
 
 
 
 
End Class

Open in new window

Untitled-picture.png
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bhaskar CP

ASKER

Thanks a lot for your timely help. It came in as water for a thirsty person.
I have a couple of things that i want to clarify...
 
>      ** Unable to make the code so that i can search with Display name
  I did the recommended change and i am able to get the display names when i search. Apparently i forgot to mention what i really want to do. I want your suggestion on finding out how to go about:

* partial name search (one should be able to type half name Eg. Jeff sutherland / jeff suth  instead of having to type "Jeff sutherland (Long Time Contractor)"

>  ** Unable to get the Managers email id of the user
I have got it working with your help. Thanks a lot.

>>      **Unable to create a plan in which the disabling,moving the user to a different ou
Havent tried it yet. Will try and let you know..


Thanks a lot for the help earlier.
forgot to add:-
   >      ** Unable to make the code so that i can search with Display name
* multiple names selection :- when multiple users with same display names are there i should be able to get those as well (eg in a popup window with display name , email and description) for all users with same name if multiple users exists..
> partial name search

Okay, that's no problem. Most attributes you can use in an LDAP search support use of Wildcards.

That means you can perform queries using these filters:

(&(objectClass=user)(objectCategory=person)(displayName=jeff suth*))
(&(objectClass=user)(objectCategory=person)(name=*sutherland*))

Including a wildcard after the value is more efficient if you have a large user base to search. Including a wildcard on either side is very inefficient but not something you'd notice if you only have a few hundred users (or the lower thousands).

> multiple names selection

Multiple searches? Or just multiple results?

To return multiple results you would switch to the FindAll() method of the DirectorySearchere.g.

Dim adResults As SearchResultCollection = mySearcher.FindAll()

Then you can loop through each result in the collection:

For Each adResult As SearchResult in adResults
  ' Do stuff
Next

I would avoid using this until it's absolutely necessary (typically only when you need to make changes):

GetDirectoryEntry

Because that makes another call to AD. Instead, have the DirectorySearcher return every value you're interested in along with the results of the search. You can have it explicitly load those with:

mySearcher.PropertiesToLoad.AddRange(New String {"displayname", "manager", "description", "mail", useraccountcontrol" })

The only catch is that when you refer to those on a search result the attribute name must be in lower case. e.g.

adResult.Properties("displayname")(0).ToString()

When I last did this I loaded the results of the search into a List filled with a custom Structure, then I bound the list to a Data Grid, saved a lot of bother with writing my own output.

Chris
Apologies for the delay in getting back to you. I definitely consider your help as extreme help and great answer for all my qns.. but would be great if i can keep this open for a couple of days if its okie with you.

Also:
multiple results..
     this is what i meant. from the above front end if i need to search for users with first name john then as per my current code it shows up only the john it can see first.
  I wantt o enable a way in which all the john with display name, loginid and description shows up in a small window or something. I am unable to think of a way.  :-( The reason is my front end design cant acomodate this i believe. can you help me plan how to go about it?

Disabling:
  I decided to go with below function on code:
Private Sub Terminatebtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Terminatebtn.Click
see if thats okie.. I tested and it works.
 
new request:(i can open a new question if you want)
1. how do i run the program with elevated privilages.. for example helpdesk need to be able to run the program with domain admin privelages..  I got the code out of some forum but i am not sure if that's the way..
see
#Region "Private Variables"

2. Everything happening with the application needs to be logged to a text file which can be kept locally if possible.
Option Explicit On
Imports System.DirectoryServices
Imports System.IO
Imports Microsoft.Win32
Imports System.Drawing
Imports Microsoft.VisualBasic
 
 
Public Class UTT
 
#Region "Private Variables"
    Public Shared ADAdminUser As String
    ' = "administrator"; //Administrator username of DC
    Public Shared ADAdminPassword As String
    ' = "password"; //Password of admin user on DC
    'This needs to have the domain name or IP address on this line
    Public Shared ADFullPath As String
    ' = "LDAP://192.168.0.3"; 
    'This must be the domain name of the domain controller (not the computer name, just the domain name)
    Public Shared ADServer As String
    ' = "sakura.com";
    '		private static string ADPath= ADFullPath ; 
    '		private static string ADUser = ADAdminUser ;
    '		private static string ADPassword = ADAdminPassword ;
 
#End Region
 
    Private Sub searchbtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles searchbtn.Click
        Dim pass1 As String = ""
        Dim pass2 As String = ""
        If samidtxt.Text <> "" Or displaynametxt.Text <> "" Then
            Dim search1 = Len(samidtxt.Text)
            Dim search2 = Len(displaynametxt.Text)
            If search1 <> "0" And search2 = "0" Then pass1 = samidtxt.Text Else 
            If search2 <> "0" And search1 = "0" Then pass1 = displaynametxt.Text
            If pass1 = samidtxt.Text Then pass2 = "1"
            If pass1 = displaynametxt.Text Then pass2 = "2"
 
            On Error Resume Next
 
            result_displaynametext.Text = GetFields(pass1, "givenname", pass2)
            result_samidtext.Text = GetFields(pass1, "sAMAccountName", pass2)
            result_desctext.Text = GetFields(pass1, "description", pass2)
            result_emailidtext.Text = GetFields(pass1, "manager", pass2)
            result_isdisabled.Text = GetFields(pass1, "userAccountControl", pass2)
            Dim managerdn As String = GetFields(pass1, "manager", pass2)
            Result_userdn.Text = GetFields(pass1, "distinguishedname", pass2)
            Dim adManager As New DirectoryEntry("LDAP://" & managerdn)
            result_managersemail.Text = adManager.Properties("mail").Value.ToString()
 
 
            If result_isdisabled.Text = "514" Then result_isdisabled.Text = "Yes" Else result_isdisabled.Text = "NO"
            If result_isdisabled.Text = "" Then result_isdisabled.Text = ""
            'If result_isdisabled.Text = "NO" Then result_isdisabled.BackColor = Color.Tomato Else 
            If result_isdisabled.Text = "Yes" Then tick.Visible = True Else tick.Visible = False
 
 
            'userAccountControl()
 
            'result_displaynametext.Text = GetFields(samidtxt.Text)
 
 
 
 
        End If
    End Sub
 
 
    Public Shared Function GetFields(ByVal UserName As String, ByVal neededvalue As String, ByVal pass2 As Integer) As String
 
        'Const DomainName As String = " schusterna.com"
        Dim DomainName As String = Environment.UserDomainName
        Dim oDirectory As New DirectoryEntry("LDAP://" & DomainName)
        Dim mySearcher As New DirectorySearcher(oDirectory)
        Dim oResult As SearchResult
        Dim sResult As String = ""
        mySearcher.SearchScope = SearchScope.Subtree
        mySearcher.ReferralChasing = ReferralChasingOption.All
        If pass2 = "1" Then
            mySearcher.Filter = "(&(objectClass=user)(sAMAccountName=" & UserName & "))"
        Else
            If pass2 = "2" Then
                mySearcher.Filter = "(&(objectClass=user)(displayname=" & UserName & "))"
            End If
        End If
        Try
            oResult = mySearcher.FindOne
            If Not oResult Is Nothing Then
                sResult = oResult.GetDirectoryEntry.Properties(neededvalue).Value.ToString()
                'Dim desc As String=(mySearcher., neededvalue:="Desc")
 
                'oResult.GetDirectoryEntry.Properties("givenName").Value.ToString()
 
            End If
        Catch ex As Exception
            Throw ex
        End Try
 
        oResult = Nothing
        mySearcher.Dispose()
        oDirectory.Dispose()
        Return sResult
    End Function
 
 
    ' <summary>
    ' Method that disables a user account in the AD and hides user's email from Exchange address lists.
    ' </summary>
    ' <param name="EmployeeID"></param>
    ' 
 
    'Public Sub DisableAccount(ByVal EmployeeID As String)
    '    Dim de As DirectoryEntry = GetDirectoryEntry()
    '    Dim ds As DirectorySearcher = New DirectorySearcher(de)
    '    ds.Filter = "(&(objectCategory=Person)(objectClass=user)(employeeID=" & EmployeeID & "))"
    '    ds.SearchScope = SearchScope.Subtree
    '    Dim results As SearchResult = ds.FindOne()
    '    If Not results Is Nothing Then
    '        Dim dey As DirectoryEntry = GetDirectoryEntry(results.Path)
    '        Dim val As Integer = CInt(dey.Properties("userAccountControl").Value)
    '        dey.Properties("userAccountControl").Value = val Or &H2
    '        dey.Properties("msExchHideFromAddressLists").Value = "TRUE"
    '        dey.CommitChanges()
    '        dey.Close()
    '    End If
    '    de.Close()
    'End Sub
 
 
 
    Private Sub UTT_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
    End Sub
 
    Private Sub Terminatebtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Terminatebtn.Click
        Dim aduser As New DirectoryEntry("LDAP://" & Result_userdn.Text)
        'aduser.NativeObject.accountdisabled = True
 
        Dim val As Integer = CInt(aduser.Properties("userAccountControl").Value)
        aduser.Properties("userAccountControl").Value = val Or &H2
 
        aduser.Properties("Description").Value = "disabled on " & Date.Today & " " & aduser.Properties("Description").Value
        aduser.CommitChanges()
        'aduser.Properties("msExchHideFromAddressLists").Value = "TRUE"
 
        Dim adTargetOU As New DirectoryEntry("LDAP://OU=New,DC=testad,DC=com")
        'adTargetOU.Invoke("MoveHere", aduser)
 
        'aduser.Invoke("MoveHere", adTargetOU)
        aduser.MoveTo(adTargetOU)
 
        'aduser.CommitChanges()
    End Sub
End Class

Open in new window

dear chris,
  were you able to take a glance at my code.

-?

Hey,

Sorry for the delay getting back to you.

I'm afraid I can't comment too much on the above, I know a fair amount about coding for AD, but when it gets into interfaces I'm a bit lost at sea. I'm a sys admin rather than a programmer so I would worry that any advice I offer about the interface would be a bit basic. Personally I would use the grid view component to display the results of a search with FindAll(), but it's about as deep as I could go.

I wasn't aware of MoveTo, it does seem more appropriate here :) I suspect the reason you were having problems with MoveHere is that it takes a string as its argument. e.g.:

adTargetOU.Invoke("MoveHere", "LDAP://" & Result_userdn.Text)

There's a second argument for MoveHere used if the account is being renamed, not entirely sure if it's required. I normally set it to Null in any code I use (which maintains the objects current name).

> 1. how do i run the program with elevated privilages..

You can bind to an object with different rights as follows:

Dim DirEntry As New DirectoryEntry("LDAP://CN=Someone,OU=Somewhere,DC=yourdomain,DC=com", "domainname\username", "password")

' Do stuff with the DirectoryEntry

Documentation for the constructor is here: http://msdn.microsoft.com/en-us/library/bw8k1as4.aspx

That would allow you to perform the actions above without the user executing the program needing rights. I suspect you may also be able to use Impersonation, but I don't know enough about it to say if that's really a viable option.

Chris
Thanks a lot chris for your help. This really helps. I will have this worked and let you know on the same.
sorry for the massive delay. i did not get to try this as i was not involved in this anymore.
Appreciate your extreme help.
-?
Excellent knowledge !!!