Display members of a group with more than 1500 members
I've got a little script which goes through our entire AD structure searching
for groups. On finding a group it then displays all the members of the group.
The final output is a text file which looks something like
group a, membera
group a, memberb
group b, member a
etc etc
The problem i have found is that any groups with over 1500 users are
truncated at 1500, so i'm not getting a true reflection of all the users in
those groups.
I've read a little that you have to specify the range to search, however, as
this is going through our entire active directory i need it to be able to
know when it hits a large group and automatically adjust to display every
single member.
any ideas?
Re: Display members of a group with more than 1500 members
Richard,
Thanks that works great. I am however having a little trouble in trying to
get it to loop through all my groups.
The idea is that i can produce a text file which contains all the group
names (or DN's if it's better for the script) and get the script to loop
through each line and query the members of each group.
I've tried putting this into the script, but it fails when it calls the sub
routine with invalid syntax
' Specify the text file of user names.
strFilePath = "c:\grouplist.txt"
' Open the file for read access.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFilePath)
' Read each line of the file.
Do Until objFile.AtEndOfStream
strNTName = Trim(objFile.ReadLine)
(rest of you script, sub routines etc)
Loop
' Clean up.
objFile.Close
It seems to fail on this line
Sub EnumMembers(strName, strOffset)
I've done a wscript.echo and the varaible strNTName is being picked up
correctly and runs through quite nicely.
Any ideas?
Re: Display members of a group with more than 1500 members
....Snip.
I got the following to work. The text file has the NetBIOS names (NT names)
of the groups. I create the ADO objects (except the Recordset object)
outside the Sub so they have global scope and only need to be created once.
Same for the dictionary object, but I had to add a step to clear the
dictionary object after each group is processed. I added a line to output
the name of the group, and modified the lines that output member names so
they do not include the group name. Note that this works also for groups
with fewer members.
============
Option Explicit
Dim strNTName, objRootDSE, strDNSDomain, adoCommand
Dim adoConnection, strBase, strAttributes, objGroupList
Dim strFile, objFile, objFSO
Const ForReading = 1
' Specify text file of group NetBIOS names.
strFile = "c:\Scripts\Groups.txt"
' Open the file for read access.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFile, ForReading)
' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
' Use ADO to search Active Directory.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open = "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
' Specify base of search and "member" attribute to retrieve.
strBase = "<LDAP://" & strDNSDomain & ">"
strAttributes = "member"
' Use dictionary object to track unique group members.
Set objGroupList = CreateObject("Scripting.Dictionary")
objGroupList.CompareMode = vbTextCompare
' Read each line of the file.
Do Until objFile.AtEndOfStream
strNTName = Trim(objFile.ReadLine)
' Skip blank lines.
If (strNTName <> "") Then
' Enumerate group members.
Call EnumMembers(strNTName, "")
End If
Loop
Sub EnumMembers(ByVal strName, ByVal strOffset)
' Recursive subroutine to enumerate members of a group,
' including nested group memberships.
' Uses range limits to handle groups with more than 1000 members.
Dim strFilter, strQuery, adoRecordset, objMember
Dim strDN, intCount, blnLast, intLowRange
Dim intHighRange, intRangeStep, objField
' Document group NetBIOS name.
Wscript.Echo strOffset & "Group: " & strName
' Filter on objects of class "group" and specified name.
strFilter = "(&(ObjectCategory=group)" _
& "(ObjectClass=group)" _
& "(sAMAccountName=" & strName & "))"
' Setup to retrieve 1000 members at a time.
blnLast = False
intRangeStep = 999
intLowRange = 0
IntHighRange = intLowRange + intRangeStep
Do While True
If (blnLast = True) Then
' If last query, retrieve remaining members.
strQuery = strBase & ";" & strFilter & ";" _
& strAttributes & ";range=" & intLowRange _
& "-*;subtree"
Else
' If not last query, retrieve 1000 members.
strQuery = strBase & ";" & strFilter & ";" _
& strAttributes & ";range=" & intLowRange & "-" _
& intHighRange & ";subtree"
End If
adoCommand.CommandText = strQuery
Set adoRecordset = adoCommand.Execute
intCount = 0
Do Until adoRecordset.EOF
For Each objField In adoRecordset.Fields
If (VarType(objField) = (vbArray + vbVariant)) _
Then
For Each strDN In objField.Value
' Escape any forward slash characters, "/", with the
backslash
' escape character. All other characters that should
be escaped are.
strDN = Replace(strDN, "/", "\/")
' Check dictionary object for duplicates.
If (objGroupList.Exists(strDN) = False) Then
' Add to dictionary object.
objGroupList.Add strDN, True
' Bind to each group member, to find "class" of
member.
Set objMember = GetObject("LDAP://" & strDN)
' Output group member.
Wscript.Echo strOffset & " Member: " & strDN
intCount = intCount + 1
If (UCase(objMember.Class) = "GROUP") Then
' If the member is class "group",
' call subroutine recursively.
Call _
EnumMembers(objMember.sAMAccountName, _
strOffset & "--")
End If
Else
' Duplicate member. Output group member.
Wscript.Echo strOffset & " Member: " & strDN _
& " (Duplicate)"
End If
Next
End If
Next
adoRecordset.MoveNext
Loop
adoRecordset.Close
' If this is the last query, exit the Do While loop.
If (blnLast = True) Then
Exit Do
End If
' If the previous query returned no members, then the previous
' query for the next 1000 members failed. Perform one more
' query to retrieve remaining members (less than 1000).
If (intCount = 0) Then
blnLast = True
Else
' Setup to retrieve next 1000 members.
intLowRange = intHighRange + 1
intHighRange = intLowRange + intRangeStep
End If
Loop
' Clear the dictionary object.
objGroupList.RemoveAll
End Sub
Re: Display members of a group with more than 1500 members
hi everyone i have a problem i can only get on internet through safe mode which i dont no why i login on my reg account and try internet and it says it cant connect also ive tried getting spybot which wont donwload with out service pack 2 and i cant even get updates on safe mode which kind of sets me back the error i get on my page is something bout the ports not being active if anyone can help much aprsheated
Re: Display members of a group with more than 1500 members
Quote:
Originally Posted by
william Z
hi everyone i have a problem i can only get on internet through safe mode which i dont no why i login on my reg account and try internet and it says it cant connect also ive tried getting spybot which wont donwload with out service pack 2 and i cant even get updates on safe mode which kind of sets me back the error i get on my page is something bout the ports not being active if anyone can help much aprsheated
First of all this is the not the proper topic to discuss your querie as it is completely different to whatever you are asking, so next time try to make a new topic for all the different queries that you have and then post it, rather than hijacking other topics. Now coming to your problem, can you specify what is the exact error message that you are getting? Are you using any firewall or internet security suite? Are you using wireless, ethernet or USB connection?