?
Solved

User Search and  Disabling Application by Active Directory

Posted on 2009-05-07
10
Medium Priority
?
621 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 3
10 Comments
 
LVL 71

Accepted Solution

by:
Chris Dent earned 2000 total points
ID: 24330558

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
ID: 24333236
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
ID: 24333250
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
Office 365 Training for Admins - 7 Day Trial

Learn how to provision tenants, synchronize on-premise Active Directory, implement Single Sign-On, customize Office deployment, and protect your organization with eDiscovery and DLP policies.  Only from Platform Scholar.

 
LVL 71

Expert Comment

by:Chris Dent
ID: 24333982
> 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
ID: 24386768
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
 
LVL 6

Author Comment

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

-?
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 24409999

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
ID: 24589164
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
ID: 24963130
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
ID: 31579199
Excellent knowledge !!!
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A company’s centralized system that manages user data, security, and distributed resources is often a focus of criminal attention. Active Directory (AD) is no exception. In truth, it’s even more likely to be targeted due to the number of companies …
Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses

801 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