Post by RBoyleI need to find a real simple way to log users using logon scripts to
my windows 2003 domain, attaching them to my users AD account and
relating the script to what security group my users are in.
You could also use the WinNT provider to retrieve a user's group
membership and use a loop and select case block to assign drives. This
requires less code and is a little easier to extend in the future:
strUserID = objNetwork.UserName
objUser = GetObject("WinNT://"&strUserID&",user")
for each group in objUser.Groups
select case group
case "groupName"
' map drive here
end select
next
The shortfall of this approach is that it doesn't use the
distinguished name of the groups, as Ryan suggests. If you have groups
in different OUs that have the same canonical name, it won't work
properly. You could do the same thing using ADSI, as Ryan suggests:
set objUser = GetObject("LDAP://"&strUserDN)
for each group in objUser.memberOf
select case group
case "groupDN"
' map drive here
end select
next
------------
I agree that the WinNT provider is easier to use. Don't take offense by what
follows, but I want to express my "philosophy" on the matter. Consider this
a matter of style if you like.
Logon scripts are important for the user experience. The code may be in use
for years. While the code is easier to develop (and perhaps read) when you
use the WinNT provider, it has the following drawbacks.
1. It is slower.
2. It only supports features available in NT networks. Many fewer attributes
are exposed.
3. It is blind to the hierarchy of AD. It does not recognize OU's or nested
domain groups.
4. It does not recognize computer group membership (in case you want to map
printers accordingly).
The first point is probably the only relevant one. Using the WinNT provider
is convenient for the coder, but results in slower code for the users.
Anyone coding logon scripts should be able to determine the Distinguished
Names of objects. Personally, I have found that shorter code is not
necessarily faster, more reliable, or easier to maintain. I like lots of
comments, white space, and indenting in my scripts so they can be understood
by anyone reading them.
Finally, I need to point out that the following will raise an error if the
user is not a member of at least 3 groups (2 groups if you use the WinNT
provider):
For Each objGroup In objUser.memberOf
The "For Each" statement expects a variant array, but objUser.memberOf is
Empty if the memberOf collection has no values, and is datatype "String" if
there is only one value. The memberOf attribute exposed by the LDAP provider
never includes the "primary" group of the user. The statement will raise an
error unless memberOf has at least two values (group DN's), not counting the
"primary" group (usually "Domain Users").
There are several ways to handle this. One is to test the datatype of
objUser.memberOf with the TypeName function. For example:
===========
arrGroups = objUser.memberOf
If IsEmpty(arrGroups) Then
' Member of no groups (except "primary"), do nothing.
ElseIf (TypeName(arrGroups) = "String") Then
' Member of one group (besides "primary").
Select Case arrGroups
Case "<group DN>"
' Map drives and/or printers.
End Select
Else
' arrGroups is Variant().
For Each strGroup In arrGroups
Select Case strGroup
Case "<group DN>"
' Map drives and/or printers.
End Select
Next
End If
=======
Notice the "Select Case" structure is repeated. Kind of ugly, but does not
slow down the script at all. Still, I would prefer using the GetEx method to
retrieve the memberOf collection, although this requires trapping the error
raised if there are no values. For example:
========
On Error Resume Next
arrGroups = objUser.GetEx("memberOf")
If (Err.Number <> 0) Then
On Error GoTo 0
' Member of no groups (except "primary"), do nothing.
Else
On Error GoTo 0
' Member of one or more groups. arrGroups is Variant()
' even if there is only one value (because GetEx was used).
For Each strGroup In arrGroups
Select Case strGroup
Case "<group DN>"
' Map drives and/or printers.
End Select
Next
End If
=======
See this link for more discussion:
http://www.rlmueller.net/MemberOf.htm
Finally, the code looks cleaner if you use the Groups method of the user
object:
========
For Each objGroup In objUser.Groups
Select Case objGroup.sAMAccountName
Case "<group pre-Windows 2000 name>"
' Map drives and/or printers.
End Select
Next
=========
I used the sAMAccountName attribute of the group object, since I assume the
LDAP provider. The point, however, is that the provider must bind to all of
the groups the user is a direct member of. This may not matter much, but if
the user is a member of many groups it will slow the script down. It would
be more efficient to retrieve the memberOf collection of DN values. The
slowest operation in logon scripts is binding to objects over the network in
Active Directory. Binding to local objects, like wshNetwork or the
dictionary object, is much faster.
--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--