Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.
Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/08/05/how-to-get-more-than-1000-group-members-including-foreign-sams-vbscript/
Post name: How to get more than 1000 group members including foreign SAMs (VBScript)
Original author: Alejandro Campos Magencio
Posting date: 2008-08-05T03:21:00+00:00


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)


Share this article:

Comments:

Comments are closed.