magnamundian2023
New Member
- Joined
- Aug 17, 2023
- Messages
- 1
- Office Version
- 365
- 2016
- 2010
- Platform
- Windows
Apologies, I guess this might be more of an LDAP question than VBA - but it's something that has been bugging me for some time and multiple attempts at searching for answers have never quite reached a solution.
So I have a fairly basic script below for fetching a list of all groups in an AD OU and a count of how many members each group has. Everything works fine until it comes across a group that has more than 1,500 members at which point it lies and acts like the group has none.
From various searching of the web this appears to be a known issue and the answer is to fetch the data in 'pages' or to specify upper/lower bounds. All examples online seem to come from the angle that your trying to get the membership of one group and often the examples are not VBA.
My workaround has been to replace Debug.Print "Empty" with the following as a 'fallback' to test any results that come back with Null for members:
However this is horribly slow on large datasets, and while I could re-write the whole thing to do a loop through each group and loop through each member of the group, the above is a stripped down version of code just to demonstrate the issue - the actual code fetches many more attributes than just cn and member, so using the GetObject method fetch each attribute for each group can take significantly longer than the approach above.
As an example the script above, used to find "empty AD groups" on our system takes 15 seconds if I allow it to incorrect report groups with over 1,500 members as "empty". Whereas if I add the second piece of code to double check all groups that claim to be empty the script takes 30 minutes but is accurate.
There must be a better way? Any thoughts?
So I have a fairly basic script below for fetching a list of all groups in an AD OU and a count of how many members each group has. Everything works fine until it comes across a group that has more than 1,500 members at which point it lies and acts like the group has none.
From various searching of the web this appears to be a known issue and the answer is to fetch the data in 'pages' or to specify upper/lower bounds. All examples online seem to come from the angle that your trying to get the membership of one group and often the examples are not VBA.
VBA Code:
Sub FetchGroupAndMembers(OU As String)
Dim CN As Object, CMD As Object, RS As Variant, ADGroup As Variant, Members As Variant, Count as Integer
Set CN = CreateObject("ADODB.Connection")
CN.Provider = "ADsDSOObject"
CN.Open "Active Directory Provider"
Set CMD = CreateObject("ADODB.Command")
CMD.ActiveConnection = CN
CMD.CommandText = "<LDAP://" & OU & ">;(objectCategory=group);cn,member;subtree"
Set RS = CMD.Execute
Do Until RS.EOF
Debug.Print RS.Fields("cn"); " = ";
Members = RS.Fields("member")
If VarType(Members) = 1 Then
Debug.Print "Empty"
Else
Debug.Print UBound(Members) + 1
End If
RS.MoveNext
Loop
RS.Close
CN.Close
Set RS = Nothing
Set CMD = Nothing
Set CN = Nothing
My workaround has been to replace Debug.Print "Empty" with the following as a 'fallback' to test any results that come back with Null for members:
VBA Code:
Set ADGroup = GetObject("LDAP://CN=" & RS.Fields("cn") & "," & OU)
Set Members = ADGroup.Members
Count = 0
For Each Entity in Members
Count = Count + 1
Next
Debug.Print Count
However this is horribly slow on large datasets, and while I could re-write the whole thing to do a loop through each group and loop through each member of the group, the above is a stripped down version of code just to demonstrate the issue - the actual code fetches many more attributes than just cn and member, so using the GetObject method fetch each attribute for each group can take significantly longer than the approach above.
As an example the script above, used to find "empty AD groups" on our system takes 15 seconds if I allow it to incorrect report groups with over 1,500 members as "empty". Whereas if I add the second piece of code to double check all groups that claim to be empty the script takes 30 minutes but is accurate.
There must be a better way? Any thoughts?