VB.NET - Active Directory to find organizational unit for a user

Hello experts,

I created a windows form application that create a record to a database.  The application will get the window user's login name as the creator of that record.  However, I also need to know where they're located.  In Active Directory, we have organizational units for various users.  Is there a way I can find out which organizational unit that user is from?

Here's my code to find out the username that is logged onto the machine:

Dim strUser as String = System.Environment.UserName

I need to find out which organizational unit this user is located within.  Any ideas?
holemaniaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

13598Commented:
Use the directorysearcher.
Here is an example to get the user's e-mail address. You will need to change the filter to get what you are looking for specifically: instead of e-mail address you need organizational unit

Using searcher As New DirectoryServices.DirectorySearcher()
'get the current root which is the domain name in DC=domain format
'remove the DC= to just have the name
Dim domainName As String = searcher.SearchRoot.Name.Replace("DC=", "")
Dim username As String = My.User.Name.ToLower.Replace(domainName, "").Replace("\", "")
'create a search/filter string to get that user
searcher.Filter = "(&(objectCategory=person)(objectClass=user)(samaccountName=" & username.Trim & "))"
'find the first user that matches the filter
Dim result As DirectoryServices.SearchResult = searcher.FindOne
If result IsNot Nothing Then
sEmailFromAddress = result.Properties("mail")(0).ToString
End If
End Using
0
13598Commented:
You need to add a reference to the system.directoryservices
 and you could try something like this:

Using searcher As New DirectoryServices.DirectorySearcher()
'get the current root which is the domain name in DC=domain format
'remove the DC= to just have the name
Dim domainName As String = searcher.SearchRoot.Name.Replace("DC=", "")
Dim username As String = My.User.Name.ToLower.Replace(domainName, "").Replace("\", "")
'create a search/filter string to get that user
searcher.Filter = "(&(objectCategory=person)(objectClass=user)(samaccountName=" & username.Trim & "))"
'find the first user that matches the filter
Dim result As DirectoryServices.SearchResult = searcher.FindOne
If result IsNot Nothing Then
sCn = result.GetDirectoryEntry().Properties("cn").Value.ToString
End If
End Using  
0
holemaniaAuthor Commented:
Thanks.  This is the result that I get.

For the username string I get the following result:  Domain and Username (flxmurphy).  DM is the domain name and xmurphy is the user.  Once it does that it gives me nothing else through the filter.

This user is in the orginazational unit "Florida".  That's what I want to pull and insert that to my table.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

13598Commented:
It depends on how your AD is setup.
Are you saying the username should be xmurphy  but you get flxmurphy?
How do you arrive at flxmurphy? Can you post your code?
0
13598Commented:
doesn't fl stand for Florida?
Do you just need to retrive the first 2 letters then something like:
yourou = mid(username.tostring,1,2)
0
holemaniaAuthor Commented:
So the OU doesn't give me the name?

Example the OU is FL, but the name is shown as Florida.  If that's the case, I guess I can use case "If" statement to tell me the name.
0
13598Commented:
That is not what I am saying. What I am saying is that you need to know your AD structure and what info goes where.
How do you get flxmurphy as username?
0
13598Commented:
I need more info on your comment: "Example the OU is FL, but the name is shown as Florida"
Are you saying the ou is FL then that is what you will get as ou.
The name is shown as Florida => where is it shown as Florida?  
0
holemaniaAuthor Commented:
Sorry, let me clarify.

Using your code, the domain is FL followed by the user name xmurphy.

'get the current root which is the domain name in DC=domain format
'remove the DC= to just have the name
Dim domainName As String = searcher.SearchRoot.Name.Replace("DC=", "")

Result is "fl".

Dim username As String = My.User.Name.ToLower.Replace(domainName, "").Replace("\", "")

Result is "flxmurphy".

In Active Directory below the AD structure if I go expand that there are folders for each organizational unit.  If I look at the organizational unit folder, it list that as Florida.  I was hoping I can pull that organizational unit folder name for the user that is in that OU.  There are a number of organizational unit folder under the domain FL.  One is Florida, Taveres, Tampa, etc.  If a user is located in one of the organizational unit, I want to pull that organizational unit name.
Sorry for the confusion.  "FL" is the domain but I need the organizational units inside of that domain since there are multiples.
0
13598Commented:
Dim username As String = My.User.Name.ToLower.Replace(domainName, "").Replace("\", "")

Result is "flxmurphy". => How can this be if domainName = "fl" ?
0
13598Commented:
This statement
My.User.Name.ToLower.Replace(domainName, "").Replace("\", "")
Is replacing the value in domainName with nothing (basically deleting it out)
If domainName is "fl" it would result in xmurphy not flxmurphy.
0
13598Commented:
What is the value in this:
messagebox.show(my.user.name)
0
13598Commented:
The only thing that would cause that result is if domainName is actually "FL" not "fl".
Change your statement to this:
Dim username As String = My.User.Name.ToLower.Replace(domainName.ToLower, "").Replace("\", "")
And let me know what you get for username.
 
0
holemaniaAuthor Commented:
It shows up as:

FL\xmurphy
0
holemaniaAuthor Commented:
If I don't use ToLower, this is what it would look like with the following code:

Dim username As String = My.User.Name.Replace(domainName, "").Replace("\", "")

FLxmurphy

Looking at the code, it's supposed to replace domainName with blank and "\" with blank.  But it doesn't seem to be doing that for some reason.
0
13598Commented:
Did you see my previous post?  =>
"The only thing that would cause that result is if
domainName is actually "FL" not "fl".
Change your statement to this:
Dim username As String = My.User.Name.ToLower.Replace(domainName.ToLower, "").Replace("\", "")
And let me know what you get for username."

0
holemaniaAuthor Commented:
I think I should be able to use the following if all that we're pulling is the username.

Using searcher as New DirectoryServices.DirectorySearcher()
Dim username as string = System.Environment.Username
searcher.filter = "(&(objectCategory=person)(objectClass=user)(sameaccountName=" & username.trim & "))"
Dim result as DirectoryServices.SearchResult = searcher.Findone
If result IsNot Nothing then
    Dim sCn As string = result.GetDirectoryEntry().Properties("cn").Value.ToString
End If
End Using

Only thing is my searcher.filter returns no result.  So i'll have to see how the AD is structure.
0
13598Commented:
What is the value you get here?
messagebox.show(username.trim)
If you are passing flxmurphy as username well it is not a valid username and that is why you get nothing.
 
This should give you username = xmurphy
Dim domainName As String = searcher.SearchRoot.Name.Replace("DC=", "")


Dim username As String = My.User.Name.ToLower.Replace(domainName.ToLower, "").Replace("\", "")
 
 
0
holemaniaAuthor Commented:
Ah I caught where I did the typo also why it's not returning anything.  "samaccountName" is where my typo is.  So the above code is pulling it now.  Looking at the result, it is showing the OU.  How do I get the OU to show in show in a string?
0
13598Commented:
What do you mean?
Isn't it showing in sCn ?
0
holemaniaAuthor Commented:
sCn is showing the full name:  Xavier Murphy

If I look at the Result string, this is what's showing:

Path  "LDAP://CN=Xavier Murphy, OU=IT, OU=FL, OU=Users, OU=Florida, DC=AD, DC=FL, DC=ContinentalSteel, DC=COM"

I want to pull the OU=Florida and not the CN name.
0
13598Commented:
Did you try
   Dim sCn As string = result.GetDirectoryEntry().Properties("ou").Value.ToString
 
0
13598Commented:
Try something like this:
If TypeOf Result.GetDirectoryEntry.Properties("ou") Is
System.Array Then
  Dim sCn As string = Result.GetDirectoryEntry.Properties("ou")(2).Value
Else
dim sCn As string = Result.GetDirectoryEntry.Properties("ou").Value
End If
 
0
holemaniaAuthor Commented:
Yes, I tried that and get the following error message:

Object reference not set to an instance of an objbect.
0
13598Commented:
Is that error on the first suggestion or the last one?
If it is on the first suggestion it is because it is an array .
Did you try the last suggestion?
0
holemaniaAuthor Commented:
It's the first one.  The 2nd one that I tried, it as well and get this error message.

Expression of type 'System.DirectoryServices.PropertyValueCollection' can never be of type 'System.Array'.
0
13598Commented:
I guess the quickest way will be to extract it from the string or we can try looping through subou entries. My AD is not setup like yours so I can't really test it.
What do you get if you use this:

result.GetDirectoryEntry().Properties("organizationalUnit").Value
 
0
13598Commented:
Add this to your code (exactly as is especially the Try/catch block) and see if any of the properties will give you FLORIDA:

For Each mys As String In result.Properties.PropertyNames
Try
MsgBox(mys.ToString & "_" & result.GetDirectoryEntry().Properties(mys.ToString).Value)
Catch ex As Exception
End Try

Next
0
holemaniaAuthor Commented:
Tried your last example and it did a loop through.  Only property with the OU is from property distinguishedname.

CN=Xavier Murphy, OU=IT, OU=FL, OU=Users,OU=Florida, DC=AD, DC=ContinentalSteel, DC=COM

I guess a parse function should be able to filter out just Florida.
0
13598Commented:
Does the distinguishedname then give you Florida, is that what you are saying?
0
holemaniaAuthor Commented:
It gives me the above example.

CN=Xavier Murphy, OU=IT, OU=FL, OU=Users,OU=Florida, DC=AD, DC=ContinentalSteel, DC=COM
0
13598Commented:
do you mean the below example:
CN=Xavier Murphy, OU=IT, OU=FL, OU=Users,OU=Florida, DC=AD, DC=ContinentalSteel, DC=COM
distinguishedname gives you all that?
0
holemaniaAuthor Commented:
Yeah but then I was able to parse it and it's giving me what I want.

Dim sCn As String = result.GetDirectoryEntry().Properties("distinguishedname").Value
lblOU.Text = Replace(Split(sCn, ", ")(4), "OU", "")
0
holemaniaAuthor Commented:
Well the above only worked for 2 sites  and pulled differently for another site.  Any idea of how I can parse it from the right to left?  The extra folder is what's throwing it off, but if I can go from right to left, it'll be same for all sites.
0
13598Commented:
This should work:
Dim sCn As String = result.GetDirectoryEntry().Properties("distinguishedname").Value.ToUpper

Dim iLength As Integer = InStr(InStrRev(sCn, "OU="), sCn, ",") - (InStrRev(sCn, "OU=") + 3)
lblOU.Text = Mid(sCn, InStrRev(sCn, "OU=") + 3, iLength)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
holemaniaAuthor Commented:
Thanks for the help.  Appreciate it.
0
13598Commented:
You are welcome.
You should probably encapsulate it with some error trapping so it doesn't blow up if there was an entry that didn't follow the rule=>
try

Dim sCn As String = result.GetDirectoryEntry().Properties("distinguishedname").Value.ToUpper

'if for some reason the entry didn't contain OU= this will blow up=>
if scn.contains("OU=") then
Dim iLength As Integer = InStr(InStrRev(sCn, "OU="), sCn, ",") - (InStrRev(sCn, "OU=") + 3)
lblOU.Text = Mid(sCn, InStrRev(sCn, "OU=") + 3, iLength)  
else
lblOU.Text = "N/A"
end if
catch
end try
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.