How to get more than 1000 group members including foreign SAMs (VBScript)
Hi all,
We may have a group in our Active Directory with members from a foreign domain. We may try to retrieve all those members with ADSI and a code like this: Using IADs::GetInfoEx for Range Retrieval. The issue with this code is that we will only be able to see the SID of foreign principals (i.e. CN=S-1-5-21-1234567890...-123,CN=ForeignSecurityPrincipals,DC=domain,DC=com), which may not be very useful for us.
The following sample (based on above Range Retrieval sample) will retrieve all members in a group (including foreign principals) and show their sAMAccountName:
' PARAMETERS.
'
strFileName = "c:\List.txt"
strGroupDN = "CN=groupName,CN=Users,DC=domainName,DC=com"
' Bind to the group with the current credentials.
'
Set oGroup = GetObject("LDAP://" & strGroupDN)
' Create file for results.
'
Set fs = CreateObject("Scripting.FileSystemObject")
Set usersFile = fs.CreateTextFile(strFileName, True)
' For compatibility with all operating systems, the number of objects
' retrieved by each query should not exceed 999. The number of objects
' to retrieve should be as close as possible to 999 to reduce the number
' of round trips to the server necessary to retrieve the objects.
rangeStep = 999
lowRange = 0
highRange = lowRange + rangeStep
Do
' Use the "member;range=<lowRange>-<highRange>" syntax.
'
strCommandText = "member;range=" & lowRange & "-" & highRange
usersFile.WriteLine(vbCrLf & "Current search command: " & _
strCommandText & vbCrLf)
' Load the specified range of members into the local cache. This
' will throw an error if the range exceeds the properties contained
' in the object. The "On Error GoTo quit" error handler will cause
' the loop to terminate when this happens.
'
On Error Resume Next
oGroup.GetInfoEx Array(strCommandText), 0
If Err.Number = &H80072020 Then
Exit Do
End If
On Error Goto 0
' Enumerate the retrieved members.
'
oMembers = oGroup.Get("member")
If vbArray And VarType(oMembers) Then
For Each oMember In oMembers
' Add the member.
'
Set oUser = GetObject("LDAP://" & oMember)
If (oUser.Class = "foreignSecurityPrincipal") Then
usersFile.WriteLine(GetForeignSAM(oUser))
Else
usersFile.WriteLine(oUser.sAMAccountName)
End If
nRetrieved = nRetrieved + 1
Next
Else
' oGroup.Get returned only one member, so add it to the list.
'
Set oUser = GetObject("LDAP://" & oMembers)
If (oUser.Class = "foreignSecurityPrincipal") Then
usersFile.WriteLine(GetForeignSAM(oUser))
Else
usersFile.WriteLine(oUser.sAMAccountName)
End If
nRetrieved = nRetrieved + 1
End If
' Increment the high and low ranges to query for the next block of
' objects.
'
lowRange = highRange + 1
highRange = lowRange + rangeStep
Loop While True
MsgBox "File """ & strFileName & """ created"
'-----------------------------------------------------------------------
' HELPER FUNCTIONS
'-----------------------------------------------------------------------
function GetForeignSAM (oUser)
' CONSTANTS.
'
ADS_SID_RAW = 0
ADS_SID_HEXSTRING = ADS_SID_RAW + 1
ADS_SID_SAM = ADS_SID_HEXSTRING + 1
ADS_SID_UPN = ADS_SID_SAM + 1
ADS_SID_SDDL = ADS_SID_UPN + 1
ADS_SID_WINNT_PATH = ADS_SID_SDDL + 1
' Get the SID
'
' Now, resolve the SID into its sAMAcountName.
'
set oADsSID = CreateObject("ADsSID")
oADsSID.SetAs ADS_SID_RAW, oUser.Get("objectSid")
' Requesting the Sam Account Name
'
GetForeignSAM = oADsSID.GetAs(ADS_SID_SAM)
end function
Note: ADsSID object is implemented in ADsSecurity.dll.
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)