"The Evil Overlord" <TheEvilOverlord@xxxxxx> wrote in
message news:7C86A42C-3764-4B0E-987A-647680610B7A@xxxxxx
>I have written a logon script. One of the first things it does is check
> Active Directory for a user's group membership. The code is below:
>
> Function ReturnGroupMembership(strUserName)
> 'Output is a recordset
> Dim objConnection
> Dim objCommand
> Dim objRecordSet
>
> Log_Event vbTab & "Creating ADODB Connection Object", boolLog_Screen,
> boolLog_File
> Set objConnection = CreateObject("ADODB.Connection")
>
> Log_Event vbTab & "Creating ADODB Command Object", boolLog_Screen,
> boolLog_File
> Set objCommand = CreateObject("ADODB.Command")
>
> Log_Event vbTab & "Setting Connection Properties", boolLog_Screen,
> boolLog_File
> objConnection.Open "Provider=ADsDSOObject;"
>
> Log_Event vbTab & "Setting Command Properties", boolLog_Screen,
> boolLog_File
> objCommand.ActiveConnection = objConnection
> objCommand.Properties("Sort On") = "sAMAccountName"
> objCommand.CommandText =
> "<LDAP://dc=domain,dc=com>;(&(objectCategory=user)(sAMAccountName=" &
> strUserName &
> ")(objectCategory=person)(!(objectClass=Contact)));memberOf;subtree"
>
> Log_Event vbTab & "Executing Search", boolLog_Screen, boolLog_File
> Set objRecordSet = objCommand.Execute
>
> Log_Event vbTab & "Returning Search Results as a Recordset",
> boolLog_Screen, boolLog_File
> Set ReturnGroupMembership = objRecordSet
> End Function
>
>
> This code generates log file entries that look like this:
>
> 2/2/2009 7:29:04 AM Getting User's Group Membership
> 2/2/2009 7:29:04 AM * Creating ADODB Connection Object
> 2/2/2009 7:29:05 AM * Creating ADODB Command Object
> 2/2/2009 7:29:05 AM * Setting Connection Properties
> 2/2/2009 7:29:05 AM * Setting Command Properties
> 2/2/2009 7:29:05 AM * Executing Search
> 2/2/2009 7:43:17 AM * Returning Search Results as a Recordset
>
>
> You can see from the last two lines of the output (above) that it took 14
> minutes for the LDAP query to return results. I'm at a loss to explain
> this.
> We have two Domain Controllers. The replication between the DCs is
> healthy.
> There are no time differences between the DCs and the workstations. Our
> windows XP clients do not display this behavior, only Vista. What should
> I
> look at to figure out why this problem exists?
>
> Thank you for your time and assistance. There is no need to sort on sAMAccountName. You don't even return that
attribute. Your filter is too complex. Since sAMAccountName must be unique
in the domain, regardless of object class, you might as well use:
objCommand.CommandText = "<LDAP://dc=domain,dc=com>;" _
& "(sAMAccountName=" & strUserName & ");" _
& "memberOf;subtree"
I cannot explain why performance would be slower on Vista, but you do not
specify parameters that could improve efficiency. I always use:
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Now ADO is generally very efficient, but in this case you are only
retrieving the information for one user, and the current user at that.
Rather than searching AD, just bind to the current user. The ADSystemInfo
object providers the Distinguished Name. Then you can retrieve the memberOf
attribute directly. In any case, the code should account for the three
possible situations: there are no DN's in the multi-valued attribute, there
is one DN, or there is more than one DN. For example:
========
' Bind to current user object.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUserDN)
' Retrieve direct group memberships.
arrGroups = objUser.memberOf
If IsNull(arrGroups) Then
' There are no group memberships.
strDisplay = "<None>"
ElseIf (TypeName(arrGroups) = "String") Then
' There is one group membership
strDisplay = arrGroups
Else
strDisplay = ""
For Each strGroup In arrGroups
If (strDisplay = "") Then
strDisplay = strGroup
Else
strDisplay = strDisplay & "," & strGroup
End If
Next
End If
Wscript.Echo "Groups: " & strDisplay
=========
Finally, if the ultimate aim is to check group membership (rather than just
displaying it), perhaps it makes more sense to bind to each group you want
to check and use the IsMember method of the group object. In brief:
========
' Bind to current user object.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUserDN)
' Bind to a group to check.
Set objGroup = GetObject("LDAP://cn=Sales,ou=West,dc=MyDomain,dc=com")
' Check if the current user is a member of this group.
If (objGroup.IsMember(objUser.AdsPath) = True) Then
' Do something.
End If
--
Richard Mueller
MVP Directory Services
Hilltop Lab -
http://www.rlmueller.net
--