#139571 - 2005-05-11 06:21 PM
Re: RFC: fnLDAPQuery() - Uses ADODB to retrieve information from AD
ChristopheM
Hey THIS is FUN
Registered: 2002-05-13
Posts: 311
Loc: STRASBOURG, France
you are too fast for me. after your post, i have modified my version to include your parameters user and pswdCode: ;Function:
; fnLDAPADQuery()
;
;Author:
; Christophe Melin (christopher.melin@cus-strasbourg.net)
;
;Version:
; 1.0 (May 11, 2005)
; herited from fnADQuery from Christopher Shilt (christopher.shilt@relizon.com) ;
;Version History:
;
;Action:
; Uses ADODB to retrieve information from Active Directory using LDAP filter.
;
;Syntax:
; fnLDAPADQuery(
; aAttributes,
; sADsPath,
; strFilter,
; Optional ORDER BY,
; Optional SCOPE
; Optional user
; optional password
; )
;
;Parameters:
; aAttributes : Required. Attribute (or array of attributes) to retrieve For
; each object. If you specify *, the query retrieves only the
; ADsPath of each object.
;
; sADsPath : Required. Specifies the ADsPath of the base of the search.
; For example, the ADsPath of the Users container in an Active
; Directory domain might be 'LDAP://CN=Users,DC=Fabrikam,DC=COM'.
;
; strFilter : Required. Specifies the query filter. You can also add wildcards
; and conditions to an LDAP search filter. The following examples
; show substrings that can be used to search the directory.
;
; Get all users:
; "objectClass=Users"
; Get entries with a common name equal to "bob":
; "cn=bob"
; Get entries with a common name beginning with "bob":
; "cn=bob*"
; Get entries containing "bob" somewhere in the common name:
; "cn=*bob*"
; Get entries with "bob" as the common name and "dull" as the surname:
; "(&(cn=bob)(sn=dull))"
;
; ORDER BY : Optional. An optional statement that generates a server-side ; sort. Charaters string with fields name separated by comma.
; Active Directory supports the sort control, but it can impact server
; performance if the results set is large. ; Be aware that Active Directory supports only a single sort key.
; Be aware that some fields are multivalued. Sort isn't allowed on these fields.
; The default is no sorting.
; ; Order by surname: ; "sn" ; ; SCOPE : Optional. Specifies the scope of a directory search.
;
; ADS_SCOPE_BASE = 0
; Limits the search to the base object. The result contains,
; at most, one object.
; ADS_SCOPE_ONELEVEL = 1
; Searches one level of the immediate children, excluding
; the base object.
; ADS_SCOPE_SUBTREE = 2 (DEFAULT)
; Searches the whole subtree, including all the children and
; the base object itself.
;
; user : Optional. username to connect to the directory.
; password : Optional. password to connect to the directory.
;
;Remarks:
;
;
;Returns:
;
; An array of attributes entered in the order specified in the aAttributes parameter.
; If only one attribute is specified each element in the array will contain the result
; of the query. If an array of attributes is specified in the WHAT parameter Each
; element in the array will contain an array of the results of the query.
;
; Sets the value of @ERROR based on success/failure.
;
;Dependencies:
;
;Example:
;
; ; == Return the Name and AdsPath of all users ===================
; $aAttributes = "Name", "AdsPath"
; $sADsPath = "LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")
; $strFilter = "(&(objectClass=User)(Name=*))"
;
; $aResults = fnLDAPADQuery($aAttributes,$sADsPath,$strFilter,"name", 2)
; @ERROR " | " @SERROR ?
;
; For Each $Result in $aResults
; If VarType($Result)>8192
; For Each $R in $Result
; $R ?
; Next
; Else
; $Result ?
; EndIf
; Next
;
; ; == Return the Name, AdsPath and members of all groups ==
; $aAttributes = "Name", "AdsPath", "member"
; $sADsPath = "LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")
; $strFilter = "(&(objectClass=group)(Name=*))"
;
; $aResults = fnLDAPADQuery($aAttributes,$sADsPath,$strFilter,"", 2)
; @ERROR " | " @SERROR ?
;
; For Each $Result in $aResults
; "=============================" ?
; If VarType($Result)>8192
; For Each $R in $Result
; If VarType($R)>8192
; for each $rr in $r
; " " $rr ?
; next
; else
; $R ?
; endif
; Next
; Else
; $Result ?
; EndIf
; Next
;
;
Function fnLDAPADQuery ($What , $sADsPath , $strFilter , Optional $OrderBy , Optional $Scope , Optional $user , Optional $Pwd )
Dim $ , $oCon , $oCommand , $oRS , $sF , $sGV , $strQuery , $sAttribsToReturn
dim $adUseClient , $adCmdText , $adSecureAuthentication , $adOpenForwardOnly , $adLockReadOnly
$adUseClient = 3
$adCmdText = 1
$adSecureAuthentication = 1
$adLockReadOnly = 1
$adOpenForwardOnly = 0
If VarType ($What ) & 8192
dim $sep
$sep = ""
$sGV = ""
For Each $sF in $What
$sGV = $sGV + $sep + '$' + 'oRS.Fields("' + $sF + '").Value'
$sep = ","
Next
$sAttribsToReturn = Join ($What ,',' )
Else
$sGV ='$' +'oRS.Fields("' +$What +'").Value'
$sAttribsToReturn = $What
EndIf
If $Scope < > "base" AND $Scope < > "onelevel" AND $Scope < > "subtree" $Scope = "subtree" EndIf
;-- Create ADO connection object for Active Directory --
$oCon = CreateObject ("ADODB.Connection" )
$oCon.Provider = "ADsDSOObject"
$oCon.Properties ("Encrypt Password" ).value = "true"
$oCon.Properties ("ADSI Flag" ).value = $adSecureAuthentication
If $User AND $Pwd
$oCon.Properties ("User ID" ).Value = $User
$oCon.Properties ("Password" ).Value = $Pwd
EndIf
$oCon.Open ( "Active Directory Provider" )
If @ERROR Exit @ERROR EndIf
;-- Create ADO command object for the connection --
$ocommand = CreateObject ("ADODB.Command" )
$ocommand.ActiveConnection = $oCon
;-- Build the filter element of the commandtext --
$strQuery = "< " + $sADsPath + ">;" + $strfilter + ";" + $sAttribsToReturn + ";" + $Scope
$ocommand.CommandText = $strQuery
If @ERROR Exit @ERROR EndIf
;-- set options --
$oCommand.Properties ( "Page Size" ).Value = 8192
$oCommand.Properties ( "Timeout" ).Value = 60
$oCommand.Properties ( "Cache Results" ).Value = 1
;-- The server-side sort does not return any results if sort by DistinguishedName --
; (see http://support.microsoft.com/kb/842637/en-us)
if $OrderBy ="distinguishedName"
;-- Create ADO recordset --
$oRS = CreateObject ("ADODB.Recordset" )
;-- Instead, the client-side sort succeeds --
$oRS.CursorLocation = $adUseClient
$oRS.Sort = $OrderBy
;-- Execute the query --
$oRS.Open ( $strQuery , $oCon , $adOpenForwardOnly , $adLockReadOnly , $adCmdText )
If @ERROR Exit @ERROR EndIf
else
if $OrderBy
$ocommand.Properties ("Sort On" ).value = $OrderBy
endif
;-- Execute the query --
$oRS = $ocommand.Execute
If @ERROR Exit @ERROR EndIf
endif
if $oRS.recordcount =0
exit 2
endif
;-- dim array because size is already known --
dim $R , $vP
redim $fnLDAPADQuery [$oRS.recordcount -1 ]
$R = 0
$oRS.MoveFirst
do
$ =Execute ('$vP=' +$sGV )
$fnLDAPADQuery [$R ]=$vP
$R =$R +1
$ =$oRS.MoveNext
until $oRS.EOF
exit 0
EndFunction
I have added the sort possibility. The code is a little bit complex because there is a bug in AD 2000 with sort on "distinguishedname". Before the final loop, i resize the array to the right size (known with $oRS.recordcount). And in the final loop, I write directly the results in the function array (by resizing with redim $fnLDAPADQuery). This prevents from using a temporary array and then copying from one array to an other. When there are many items, it's more efficient and reduce the use of memory.
_________________________
Christophe
Top
Moderator: Glenn Barnas , NTDOC , Arend_ , Jochen , Radimus , Allen , ShaneEP , Ruud van Velsen , Mart
0 registered
and 846 anonymous users online.