Solved

User Search and  Disabling Application by Active Directory

Posted on 2009-05-07
10
613 Views
Last Modified: 2013-11-27
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
0
Comment
Question by:question
  • 7
  • 3
10 Comments
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
Comment Utility

Just a quick note first... any code examples below are from memory, nothing to test it on at the moment. I hope I didn't make any glaring errors :)

>      ** Unable to make the code so that i can search with Display name

The filter you want for searching by display name is like this

(&(objectClass=user)(objectCategory=person)(displayName= ... ))

Where you would have the code insert the value you want to search in place of "...".

>      ** Unable to get the Managers email id of the user

To get that you must either construct a search that returns the Manager, or connect to the Managers account as a DirectoryEntry.

For example, if you've take the "manager" field from a user you could run:

Dim adManager As New DirectoryEntry("LDAP://" & strManager)
Dim managerEmail As String = adManager.Properties("mail").Value.ToString()

>      **Unable to create a plan in which the disabling,moving the user to a different ou
> can be done.

Disabling can be done in one of two ways. Either modify the userAccountControl value, a bitwise comparison and addition of the decimal value 2 will disable the account.

Alternatively set the AccountDisabled Property. I believe setting the AccountDisabled Property is a bit less obvious, you may have to access it like this:

adUser.NativeObject.AccountDisabled = True

Afraid I can't test it at the moment, but I can in the morning if you're still having trouble with it.

Finally, to move an account you need to invoke the MoveHere method on the container you want to move it to. For example:

Dim adTargetOU As New DirectoryEntry("LDAP://OU=somewhereNew,DC=yourdomain,DC=com")
adTarget.Invoke("MoveHere", adUser.ADSPath)

Probably needs a bit of prodding to get it working. Need more detail? :)

Chris
0
 
LVL 6

Author Comment

by:question
Comment Utility
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.
0
 
LVL 6

Author Comment

by:question
Comment Utility
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..
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility
> 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
0
 
LVL 6

Author Comment

by:question
Comment Utility
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

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 6

Author Comment

by:question
Comment Utility
dear chris,
  were you able to take a glance at my code.

-?
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility

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
0
 
LVL 6

Author Comment

by:question
Comment Utility
Thanks a lot chris for your help. This really helps. I will have this worked and let you know on the same.
0
 
LVL 6

Author Comment

by:question
Comment Utility
sorry for the massive delay. i did not get to try this as i was not involved in this anymore.
Appreciate your extreme help.
-?
0
 
LVL 6

Author Closing Comment

by:question
Comment Utility
Excellent knowledge !!!
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
Disabling the Directory Sync Service Account in Office 365 will stop directory synchronization from working.
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles from a Windows Server 2008 domain controller to a Windows Server 2012 domain controlle…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now