Jamie
Jamie

Reputation: 1679

Searching Active Directory for Members of Specific Group Fails When User Has No Group

the following code is supposed to run through all users in active directory and find everyone in a specific group. Once it gets the users, it will add them to a datatable which will be the source of a gridview for a final export to Excel.

However, while running and stepping through, I've noticed it gets stopped on a certain user with no group. I tried adding a conditional statement to skip that instance, but it isn't working, the code still stops running when it finds the user with no group.

Can someone show me what I could be doing differently? Caveat: This is from a legacy site that I inherited, knowing very little about active directory and being a novice vb coder.

Dim entry As DirectoryEntry = New DirectoryEntry("LDAP://DOMAIN.EDU", "USERNAME", "PASSWORD", AuthenticationTypes.Secure)
    Dim search As DirectorySearcher = New DirectorySearcher(entry) With {
        .Filter = "(&(objectCategory=User)(objectClass=person))",
        .PageSize = 4000
    }
    search.PropertiesToLoad.Add("userPrincipalName").ToString
    search.PropertiesToLoad.Add("name").ToString
    Dim mySearchResultColl As SearchResultCollection = search.FindAll
    Dim results As DataTable = New DataTable
    results.Columns.Add("User ID")        
    results.Columns.Add("Full Name")
    Dim CurrRow = 0

    For Each sr As SearchResult In mySearchResultColl

        Dim dr As DataRow = results.NewRow
        Dim de As DirectoryEntry = sr.GetDirectoryEntry
        !!!! line below is the problem !!!!
        If de.Properties("memberOf") IsNot Nothing AndAlso de.Properties("memberOf").Value.ToString = "CN=MYGROUP,OU=Security Groups,OU=Students,DC=DOMAIN,DC=edu" Then 
            dr("User ID") = de.Properties("userPrincipalName").Value           
            dr("Full Name") = de.Properties("name").Value
            results.Rows.Add(dr)
            de.Close
        End If
    Next

    gvNot.DataSource = results
    gvNot.DataBind()
    gvNot.Visible = True
    gvAgreed.Visible = False
    ExportToExcel("notagreed", gvNot)

Upvotes: 0

Views: 531

Answers (2)

Ashish
Ashish

Reputation: 16

Try using String.Equals function with StringComparer.OrdinalIgnoreCase parameter instead of using equals operator. Also what's the error you are getting?

Upvotes: 0

Gabriel Luci
Gabriel Luci

Reputation: 40868

I'm not sure what you mean by "gets stopped", but you can change this up so it performs better and fixes any issues you have.

  1. This loop will take forever since you have to inspect every user on the domain. If you only want users in a specific group, then you can speed this up by only asking for members of the group. You do that by adding a condition in the query for the memberOf attribute. This way, you only get results you care about.

(Note that if you have more than one domain in your forest, using memberOf to find members may not work the way you want. I wrote about that here. But if you only have one domain, then it'll be fine.)

  1. In the loop, don't create a DirectoryEntry for each result, since that will force it to go back out to AD and request the attributes for the object again, even though you already got what you needed in the search results. So use the values in the SearchResult object instead.

  2. The documentation for SearchResultCollection says:

Due to implementation restrictions, the SearchResultCollection class cannot release all of its unmanaged resources when it is garbage collected. To prevent a memory leak, you must call the Dispose method when the SearchResultCollection object is no longer needed.

So you should put that in a Using clause.

  1. I'm also not sure why you're calling ToString on PropertiesToLoad.Add when you're not using the return value. You can just remove that.

Here it is all together:

Dim entry As DirectoryEntry = New DirectoryEntry("LDAP://DOMAIN.EDU", "USERNAME", "PASSWORD", AuthenticationTypes.Secure)
Dim search As DirectorySearcher = New DirectorySearcher(entry) With {
    .Filter = "(&(objectCategory=User)(objectClass=person)(memberOf=CN=MYGROUP,OU=Security Groups,OU=Students,DC=DOMAIN,DC=edu))",
    .PageSize = 4000
}
search.PropertiesToLoad.Add("userPrincipalName")
search.PropertiesToLoad.Add("name")

Dim results As DataTable = New DataTable
results.Columns.Add("User ID")        
results.Columns.Add("Full Name")
Dim CurrRow = 0

Using mySearchResultColl As SearchResultCollection = search.FindAll
    For Each sr As SearchResult In mySearchResultColl

        Dim dr As DataRow = results.NewRow
        dr("User ID") = sr.Properties("userPrincipalName")(0)
        dr("Full Name") = sr.Properties("name")(0)
        results.Rows.Add(dr)
    Next
End Using

gvNot.DataSource = results
gvNot.DataBind()
gvNot.Visible = True
gvAgreed.Visible = False
ExportToExcel("notagreed", gvNot)

I don't see you using CurrRow anywhere, but I left it in case you're using it in other code you didn't show here.

Upvotes: 1

Related Questions