Sample download: http://code.msdn.microsoft.com/VBGetUserGroupInAD-a94dc080
Today’s code sample illustrates how to perform a search on the user’s group membership in Active Directory. This demonstrates the recursive looping method. Also it shows how to get the Object SID for the group. The sample was written by Microsoft Support Escalation Engineer Shaleen Thapa.
You can find more code samples that demonstrate the most typical programming scenarios by using Microsoft All-In-One Code Framework Sample Browser or Sample Browser Visual Studio extension. They give you the flexibility to search samples, download samples on demand, manage the downloaded samples in a centralized place, and automatically be notified about sample updates. If it is the first time that you hear about Microsoft All-In-One Code Framework, please watch the introduction video on Microsoft Showcase, or read the introduction on our homepage http://1code.codeplex.com/.
This sample application demonstrates how to perform a search on the user’s group membership in Active Directory. This demonstrates the recursive looping method. Also it shows how to get the Object SID for the group
You can execute this sample by creating the exe via Visual Studio.
In order to execute the application, you must need to consider the followings:
We are using System.DirectoryServices namespace to perform a search on AD. We will be passing the distinguishedName of the domain with the username whose membership we would like to fetch.
Once we found the user, we will read the memberOF attribute’s value. It is one of the possibilities that the group can be member of another group as well; in this case we would need to do a recursive looping.
''' <summary> ''' This function will search the user. ''' Once user is found, it will get it's memberOF attribute's value. ''' </summary> ''' <param name="domainDN">distinguishedName of the domain</param> ''' <param name="sAMAccountName"> ''' sAMAccountName of the user for which we are searching the group membership in AD ''' </param> ''' <returns></returns> ''' <remarks></remarks> Public Function GetUserGroups(ByVal domainDN As String, ByVal sAMAccountName As String) As List(Of String) Try 'Create the DirectoryEntry object to bind the distingusihedName of your domain Using rootDE As New DirectoryEntry("LDAP://" & domainDN) 'Create a DirectorySearcher for performing a search on abiove created DirectoryEntry Using dSearcher As New DirectorySearcher(rootDE) 'Create the sAMAccountName as filter dSearcher.Filter = "(&(sAMAccountName=" & sAMAccountName & ")(objectClass=User)(objectCategory=Person))" dSearcher.PropertiesToLoad.Add("memberOf") dSearcher.ClientTimeout.Add(New TimeSpan(0, 20, 0)) dSearcher.ServerTimeLimit.Add(New TimeSpan(0, 20, 0)) 'Search the user in AD Dim sResult As SearchResult = dSearcher.FindOne If sResult Is Nothing Then Throw New ApplicationException("No user with username " & sAMAccountName & " could be found in the domain") Else Dim lGroups As New List(Of String) 'Once we get the userm let us get all the memberOF attibute's value For Each grp In sResult.Properties("memberOf") Dim sGrpName As String = CStr(grp).Remove(0, 3) 'Bind to this group Dim deTempForSID As New DirectoryEntry("LDAP://" + grp.ToString().Replace("/", "\/")) Try deTempForSID.RefreshCache() 'Get the objectSID which is Byte array Dim objectSid As Byte() = DirectCast(deTempForSID.Properties("objectSid").Value, Byte()) 'Pass this Byte array to Security.Principal.SecurityIdentifier to convert this 'byte array to SDDL format Dim SID As New System.Security.Principal.SecurityIdentifier(objectSid, 0) If sGrpName.Contains(",CN") Then sGrpName = sGrpName.Remove(sGrpName.IndexOf(",CN")) ElseIf sGrpName.Contains(",OU") Then sGrpName = sGrpName.Remove(sGrpName.IndexOf(",OU")) End If 'Perform a recursive search on these groups. RecursivelyGetGroups(dSearcher, lGroups, sGrpName, SID.ToString()) Catch ex As Exception Console.WriteLine("Error while binding to path : " + grp.ToString()) Console.WriteLine(ex.Message.ToString()) End Try Next Return lGroups End If End Using End Using Catch ex As Exception Console.WriteLine("Please check the distinguishedName of the domain if it is as per your domain or not?") Console.WriteLine(ex.Message.ToString()) End End Try End Function ''' <summary> ''' This function will perform a recursive search and will add only one occurance of ''' the group found in the enumeration. ''' </summary> ''' <param name="dSearcher">DirectorySearcher object to perform search</param> ''' <param name="lGroups">List of the Groups from AD</param> ''' <param name="sGrpName"> ''' Group name which needs to be checked inside the Groups collection ''' </param> ''' <param name="SID">objectSID of the object</param> ''' <remarks></remarks> Public Sub RecursivelyGetGroups(ByVal dSearcher As DirectorySearcher, ByVal lGroups As List(Of String), ByVal sGrpName As String, ByVal SID As String) 'Check if the group has already not found If Not lGroups.Contains(sGrpName) Then lGroups.Add(sGrpName & " : " & SID) 'Now perform the search based on this group dSearcher.Filter = "(&(objectClass=grp)(CN=" & sGrpName & "))".Replace("\", "\\") dSearcher.ClientTimeout.Add(New TimeSpan(0, 2, 0)) dSearcher.ServerTimeLimit.Add(New TimeSpan(0, 2, 0)) 'Search this group Dim GroupSearchResult As SearchResult = dSearcher.FindOne If Not GroupSearchResult Is Nothing Then For Each grp In GroupSearchResult.Properties("memberOf") Dim ParentGroupName As String = CStr(grp).Remove(0, 3) 'Bind to this group Dim deTempForSID As New DirectoryEntry("LDAP://" + grp.ToString().Replace("/", "\/")) Try 'Get the objectSID which is Byte array Dim objectSid As Byte() = DirectCast(deTempForSID.Properties("objectSid").Value, Byte()) 'Pass this Byte array to Security.Principal.SecurityIdentifier to convert this 'byte array to SDDL format Dim ParentSID As New System.Security.Principal.SecurityIdentifier(objectSid, 0) If ParentGroupName.Contains(",CN") Then ParentGroupName = ParentGroupName.Remove(ParentGroupName.IndexOf(",CN")) ElseIf ParentGroupName.Contains(",OU") Then ParentGroupName = ParentGroupName.Remove(ParentGroupName.IndexOf(",OU")) End If RecursivelyGetGroups(dSearcher, lGroups, ParentGroupName, ParentSID.ToString()) Catch ex As Exception Console.WriteLine("Error while binding to path : " + grp.ToString()) Console.WriteLine(ex.Message.ToString()) End Try Next End If End If End Sub
For more information on System.DirectoryServices Namespace http://msdn.microsoft.com/en-us/library/system.directoryservices.aspx , DirectoryEntry Class http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx & DirectorySearcher Class http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx
For System.Security.Principal.SecurityIdentifier http://msdn.microsoft.com/en-us/library/system.security.principal.securityidentifier.aspx
Why do I get the following after executing
Dim sResult As SearchResult = dSearcher.FindOne
+ ex {System.DirectoryServices.DirectoryServicesCOMException (0x8007202B): A referral was returned from the server. at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail) at System.DirectoryServices.DirectoryEntry.Bind() at System.DirectoryServices.DirectoryEntry.get_AdsObject() at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne) at System.DirectoryServices.DirectorySearcher.FindOne() at VBGetUserGroupInAD.MainModule.GetUserGroups(String domainDN, String sAMAccountName) in C:\Users\davej.FFMCD1\Documents\Visual Studio 2010\Projects\Get user group membership\VB\VBGetUserGroupInAD\MainModule.vb:line 64} System.Exception