Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > VB Script

Vista Tutorial - Map network printers based on OU user is in within Active Director

Reply
 
Old 07-01-2009   #1 (permalink)
Rich
Guest


 
 

Map network printers based on OU user is in within Active Director

I have users spread out in Active Directory under 20 sub-OU's of a Users OU.
What I'd like to do is have a GPO on Users call a script that will map
different printers based on what sub-OU the user account is in. Does anyone
have a script that will do that? I'm assuming its possible to do.

My System SpecsSystem Spec
Old 07-01-2009   #2 (permalink)
Richard Mueller [MVP]
Guest


 
 

Re: Map network printers based on OU user is in within Active Director

Rich wrote:
Quote:

>I have users spread out in Active Directory under 20 sub-OU's of a Users
>OU.
> What I'd like to do is have a GPO on Users call a script that will map
> different printers based on what sub-OU the user account is in. Does
> anyone
> have a script that will do that? I'm assuming its possible to do.
It's more common to map printers according to group membership. To determine
the parent OU you can use the Parent method of the user object, which
returns the Distinguished Name of the OU. For example:
========
Option Explicit
Dim objSysInfo, strUserDN, objUser
Dim strParentDN, objNetwork

' Retrieve DN of current user.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
' Escape any forward slash characters.
strUserDN = Replace(strUserDN, "/", "\/")

' Bind to current user object.
Set objUser = GetObject("LDAP://" & strUserDN)

' Retrieve DN of parent OU/Container.
strParentDN = objUser.Parent

' Map printers according to parent OU.
Set objNetwork = CreateObject("Wscript.Network")
Select Case LCase(strParentDN)
Case "ou=west,ou=users,dc=mydomain,dc=com"
objNetwork.AddWindowsPrinterConnection "\\PrintServer1\HPLaser2"
objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
Case "ou=east,ou=users,dc=mydomain,dc=com"
objNetwork.AddWindowsPrinterConnection "\\PrintServer2\HPLaser3"
objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
End Select
=======
Using the DN of the parent OU makes sure the name is unique. You can also
parse for the Relative Distinguished Name (RDN), but that may not be unique.
Code to parse for the RDN could be similar to:
=========
Dim objSysInfo, strUserDN, objUser
Dim strOUPath, arrContainers, arrOU, strOU

' Retrieve DN of current user.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
' Escape any forward slash characters.
strUserDN = Replace(strUserDN, "/", "\/")

' Bind to current user object.
Set objUser = GetObject("LDAP://" & strUserDN)

' Retrieve DN of parent OU/Container.
strOUPath = objUser.Parent

' Replace any escaped commas with Chr(164).
strOUPath = Replace(strOUPath, "\,", Chr(164))

' Parse Parent DN into comma delimited components.
arrContainers = Split(strOUPath, ",")

' Parse the first component to retrieve name of the OU/Container.
arrOU = Split(arrContainers(0), "=")
strOU = arrOU(1)

' Restore any escaped commas.
strOU = Replace(strOU, Chr(164), "\,")

Wscript.Echo "User is in OU/Container " & strOU
========
Again, you can use a Select Case construction to map printers. If you know
your AD has no DN's with embedded commas or forward slashes you can
eliminate the code that accounts for that, but it doesn't hurt in any case.

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--


My System SpecsSystem Spec
Old 07-02-2009   #3 (permalink)
Rich
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

I never thought of doing it based on group membership, I might be able to do
it like that since you said it's better. How would I do it based on group
membership?

"Richard Mueller [MVP]" wrote:
Quote:

> Rich wrote:
>
Quote:

> >I have users spread out in Active Directory under 20 sub-OU's of a Users
> >OU.
> > What I'd like to do is have a GPO on Users call a script that will map
> > different printers based on what sub-OU the user account is in. Does
> > anyone
> > have a script that will do that? I'm assuming its possible to do.
>
> It's more common to map printers according to group membership. To determine
> the parent OU you can use the Parent method of the user object, which
> returns the Distinguished Name of the OU. For example:
> ========
> Option Explicit
> Dim objSysInfo, strUserDN, objUser
> Dim strParentDN, objNetwork
>
> ' Retrieve DN of current user.
> Set objSysInfo = CreateObject("ADSystemInfo")
> strUserDN = objSysInfo.UserName
> ' Escape any forward slash characters.
> strUserDN = Replace(strUserDN, "/", "\/")
>
> ' Bind to current user object.
> Set objUser = GetObject("LDAP://" & strUserDN)
>
> ' Retrieve DN of parent OU/Container.
> strParentDN = objUser.Parent
>
> ' Map printers according to parent OU.
> Set objNetwork = CreateObject("Wscript.Network")
> Select Case LCase(strParentDN)
> Case "ou=west,ou=users,dc=mydomain,dc=com"
> objNetwork.AddWindowsPrinterConnection "\\PrintServer1\HPLaser2"
> objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
> Case "ou=east,ou=users,dc=mydomain,dc=com"
> objNetwork.AddWindowsPrinterConnection "\\PrintServer2\HPLaser3"
> objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
> End Select
> =======
> Using the DN of the parent OU makes sure the name is unique. You can also
> parse for the Relative Distinguished Name (RDN), but that may not be unique.
> Code to parse for the RDN could be similar to:
> =========
> Dim objSysInfo, strUserDN, objUser
> Dim strOUPath, arrContainers, arrOU, strOU
>
> ' Retrieve DN of current user.
> Set objSysInfo = CreateObject("ADSystemInfo")
> strUserDN = objSysInfo.UserName
> ' Escape any forward slash characters.
> strUserDN = Replace(strUserDN, "/", "\/")
>
> ' Bind to current user object.
> Set objUser = GetObject("LDAP://" & strUserDN)
>
> ' Retrieve DN of parent OU/Container.
> strOUPath = objUser.Parent
>
> ' Replace any escaped commas with Chr(164).
> strOUPath = Replace(strOUPath, "\,", Chr(164))
>
> ' Parse Parent DN into comma delimited components.
> arrContainers = Split(strOUPath, ",")
>
> ' Parse the first component to retrieve name of the OU/Container.
> arrOU = Split(arrContainers(0), "=")
> strOU = arrOU(1)
>
> ' Restore any escaped commas.
> strOU = Replace(strOU, Chr(164), "\,")
>
> Wscript.Echo "User is in OU/Container " & strOU
> ========
> Again, you can use a Select Case construction to map printers. If you know
> your AD has no DN's with embedded commas or forward slashes you can
> eliminate the code that accounts for that, but it doesn't hurt in any case.
>
> --
> Richard Mueller
> MVP Directory Services
> Hilltop Lab - http://www.rlmueller.net
> --
>
>
>
My System SpecsSystem Spec
Old 07-02-2009   #4 (permalink)
Richard Mueller [MVP]
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

You would create a group for each printer. Then to test for user membership
in the group the code could be similar to:
=======
Option Explicit
Dim objSysInfo, strUserDN, objUser
Dim objGroup, objNetwork

' Retrieve DN of current user.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName

' Bind to current user object.
Set objUser = GetObject("LDAP://" & strUserDN)

Set objNetwork = CreateObject("Wscript.Network")
' Bind to group.
Set objGroup = GetObject("LDAP://cn=Test Group,ou=West,dc=MyDomain,dc=com")

' Check for membership in the group.
If (objGroup.IsMember(objUser.AdsPath) = True) Then
objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
End If
========
I say this method is better because users should be placed in OU's for two
purposes. To organize them as you wish in your organization, and to apply
the proper Group Policy. It makes things complicated to also use OU's to
define printers. You probably have many more printers than logical units in
your organization. Groups just have more flexibility.

Also, if users can use any computer (or many computers), and computers are
fixed (not laptops that roam with the users), it can make sense to map
printers according to the group the computer object is a member of. I did
this for years. I made my desktop computers member of the appropriate group
for the nearest printer. In the logon script I used code similar to:
==========
' Retrieve DN of computer object.
Set objSysInfo = CreateObject("ADSystemInfo")
strComputerDN = objSysInfo.ComputerName

' Bind to computer object.
Set objComputer = GetObject("LDAP://" & strComputerDN)

Set objNetwork = CreateObject("Wscript.Network")

' Bind to group.
Set objGroup = GetObject("LDAP://cn=Test Group,ou=West,dc=MyDomain,dc=com")

' Check for membership in the group.
If (objGroup.IsMember(objComputer.AdsPath) = True) Then
objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
End If
======
There are many methods to check for group membership, but the above is the
simplest if you are only concerned with direct membership (you don't care
about membership due to group nesting).

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--

"Rich" <richjone@xxxxxx> wrote in message
news:78DFCE10-EC54-48CD-9BB7-4EE060B6C7BC@xxxxxx
Quote:

>I never thought of doing it based on group membership, I might be able to
>do
> it like that since you said it's better. How would I do it based on group
> membership?
>
> "Richard Mueller [MVP]" wrote:
>
Quote:

>> Rich wrote:
>>
Quote:

>> >I have users spread out in Active Directory under 20 sub-OU's of a Users
>> >OU.
>> > What I'd like to do is have a GPO on Users call a script that will map
>> > different printers based on what sub-OU the user account is in. Does
>> > anyone
>> > have a script that will do that? I'm assuming its possible to do.
>>
>> It's more common to map printers according to group membership. To
>> determine
>> the parent OU you can use the Parent method of the user object, which
>> returns the Distinguished Name of the OU. For example:
>> ========
>> Option Explicit
>> Dim objSysInfo, strUserDN, objUser
>> Dim strParentDN, objNetwork
>>
>> ' Retrieve DN of current user.
>> Set objSysInfo = CreateObject("ADSystemInfo")
>> strUserDN = objSysInfo.UserName
>> ' Escape any forward slash characters.
>> strUserDN = Replace(strUserDN, "/", "\/")
>>
>> ' Bind to current user object.
>> Set objUser = GetObject("LDAP://" & strUserDN)
>>
>> ' Retrieve DN of parent OU/Container.
>> strParentDN = objUser.Parent
>>
>> ' Map printers according to parent OU.
>> Set objNetwork = CreateObject("Wscript.Network")
>> Select Case LCase(strParentDN)
>> Case "ou=west,ou=users,dc=mydomain,dc=com"
>> objNetwork.AddWindowsPrinterConnection "\\PrintServer1\HPLaser2"
>> objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
>> Case "ou=east,ou=users,dc=mydomain,dc=com"
>> objNetwork.AddWindowsPrinterConnection "\\PrintServer2\HPLaser3"
>> objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
>> End Select
>> =======
>> Using the DN of the parent OU makes sure the name is unique. You can also
>> parse for the Relative Distinguished Name (RDN), but that may not be
>> unique.
>> Code to parse for the RDN could be similar to:
>> =========
>> Dim objSysInfo, strUserDN, objUser
>> Dim strOUPath, arrContainers, arrOU, strOU
>>
>> ' Retrieve DN of current user.
>> Set objSysInfo = CreateObject("ADSystemInfo")
>> strUserDN = objSysInfo.UserName
>> ' Escape any forward slash characters.
>> strUserDN = Replace(strUserDN, "/", "\/")
>>
>> ' Bind to current user object.
>> Set objUser = GetObject("LDAP://" & strUserDN)
>>
>> ' Retrieve DN of parent OU/Container.
>> strOUPath = objUser.Parent
>>
>> ' Replace any escaped commas with Chr(164).
>> strOUPath = Replace(strOUPath, "\,", Chr(164))
>>
>> ' Parse Parent DN into comma delimited components.
>> arrContainers = Split(strOUPath, ",")
>>
>> ' Parse the first component to retrieve name of the OU/Container.
>> arrOU = Split(arrContainers(0), "=")
>> strOU = arrOU(1)
>>
>> ' Restore any escaped commas.
>> strOU = Replace(strOU, Chr(164), "\,")
>>
>> Wscript.Echo "User is in OU/Container " & strOU
>> ========
>> Again, you can use a Select Case construction to map printers. If you
>> know
>> your AD has no DN's with embedded commas or forward slashes you can
>> eliminate the code that accounts for that, but it doesn't hurt in any
>> case.
>>
>> --
>> Richard Mueller
>> MVP Directory Services
>> Hilltop Lab - http://www.rlmueller.net
>> --
>>
>>
>>

My System SpecsSystem Spec
Old 07-02-2009   #5 (permalink)
Rich
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

My scripting knowledge is limited, so please bare with me. How would I do
this for multiple groups, determining multiple sets of printers? Do I just
keep copying and pasting over and over from the setObjGroup line till the
end?

or could i just make a huge If or case type statement saying if in group
Group1 map these printers, if in group Group2 map these printers, etc etc

I understand what your script is doing I think, just not sure how to best
scale it to probably 30 groups without increasing my users login time because
of a script. It already takes them log enough to log in because of old
hardware, if it takes longer i might have a mutiny on my hands ;-)

"Richard Mueller [MVP]" wrote:
Quote:

> You would create a group for each printer. Then to test for user membership
> in the group the code could be similar to:
> =======
> Option Explicit
> Dim objSysInfo, strUserDN, objUser
> Dim objGroup, objNetwork
>
> ' Retrieve DN of current user.
> Set objSysInfo = CreateObject("ADSystemInfo")
> strUserDN = objSysInfo.UserName
>
> ' Bind to current user object.
> Set objUser = GetObject("LDAP://" & strUserDN)
>
> Set objNetwork = CreateObject("Wscript.Network")
> ' Bind to group.
> Set objGroup = GetObject("LDAP://cn=Test Group,ou=West,dc=MyDomain,dc=com")
>
> ' Check for membership in the group.
> If (objGroup.IsMember(objUser.AdsPath) = True) Then
> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
> End If
> ========
> I say this method is better because users should be placed in OU's for two
> purposes. To organize them as you wish in your organization, and to apply
> the proper Group Policy. It makes things complicated to also use OU's to
> define printers. You probably have many more printers than logical units in
> your organization. Groups just have more flexibility.
>
> Also, if users can use any computer (or many computers), and computers are
> fixed (not laptops that roam with the users), it can make sense to map
> printers according to the group the computer object is a member of. I did
> this for years. I made my desktop computers member of the appropriate group
> for the nearest printer. In the logon script I used code similar to:
> ==========
> ' Retrieve DN of computer object.
> Set objSysInfo = CreateObject("ADSystemInfo")
> strComputerDN = objSysInfo.ComputerName
>
> ' Bind to computer object.
> Set objComputer = GetObject("LDAP://" & strComputerDN)
>
> Set objNetwork = CreateObject("Wscript.Network")
>
> ' Bind to group.
> Set objGroup = GetObject("LDAP://cn=Test Group,ou=West,dc=MyDomain,dc=com")
>
> ' Check for membership in the group.
> If (objGroup.IsMember(objComputer.AdsPath) = True) Then
> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
> End If
> ======
> There are many methods to check for group membership, but the above is the
> simplest if you are only concerned with direct membership (you don't care
> about membership due to group nesting).
>
> --
> Richard Mueller
> MVP Directory Services
> Hilltop Lab - http://www.rlmueller.net
> --
>
> "Rich" <richjone@xxxxxx> wrote in message
> news:78DFCE10-EC54-48CD-9BB7-4EE060B6C7BC@xxxxxx
Quote:

> >I never thought of doing it based on group membership, I might be able to
> >do
> > it like that since you said it's better. How would I do it based on group
> > membership?
> >
> > "Richard Mueller [MVP]" wrote:
> >
Quote:

> >> Rich wrote:
> >>
> >> >I have users spread out in Active Directory under 20 sub-OU's of a Users
> >> >OU.
> >> > What I'd like to do is have a GPO on Users call a script that will map
> >> > different printers based on what sub-OU the user account is in. Does
> >> > anyone
> >> > have a script that will do that? I'm assuming its possible to do.
> >>
> >> It's more common to map printers according to group membership. To
> >> determine
> >> the parent OU you can use the Parent method of the user object, which
> >> returns the Distinguished Name of the OU. For example:
> >> ========
> >> Option Explicit
> >> Dim objSysInfo, strUserDN, objUser
> >> Dim strParentDN, objNetwork
> >>
> >> ' Retrieve DN of current user.
> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> strUserDN = objSysInfo.UserName
> >> ' Escape any forward slash characters.
> >> strUserDN = Replace(strUserDN, "/", "\/")
> >>
> >> ' Bind to current user object.
> >> Set objUser = GetObject("LDAP://" & strUserDN)
> >>
> >> ' Retrieve DN of parent OU/Container.
> >> strParentDN = objUser.Parent
> >>
> >> ' Map printers according to parent OU.
> >> Set objNetwork = CreateObject("Wscript.Network")
> >> Select Case LCase(strParentDN)
> >> Case "ou=west,ou=users,dc=mydomain,dc=com"
> >> objNetwork.AddWindowsPrinterConnection "\\PrintServer1\HPLaser2"
> >> objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
> >> Case "ou=east,ou=users,dc=mydomain,dc=com"
> >> objNetwork.AddWindowsPrinterConnection "\\PrintServer2\HPLaser3"
> >> objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
> >> End Select
> >> =======
> >> Using the DN of the parent OU makes sure the name is unique. You can also
> >> parse for the Relative Distinguished Name (RDN), but that may not be
> >> unique.
> >> Code to parse for the RDN could be similar to:
> >> =========
> >> Dim objSysInfo, strUserDN, objUser
> >> Dim strOUPath, arrContainers, arrOU, strOU
> >>
> >> ' Retrieve DN of current user.
> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> strUserDN = objSysInfo.UserName
> >> ' Escape any forward slash characters.
> >> strUserDN = Replace(strUserDN, "/", "\/")
> >>
> >> ' Bind to current user object.
> >> Set objUser = GetObject("LDAP://" & strUserDN)
> >>
> >> ' Retrieve DN of parent OU/Container.
> >> strOUPath = objUser.Parent
> >>
> >> ' Replace any escaped commas with Chr(164).
> >> strOUPath = Replace(strOUPath, "\,", Chr(164))
> >>
> >> ' Parse Parent DN into comma delimited components.
> >> arrContainers = Split(strOUPath, ",")
> >>
> >> ' Parse the first component to retrieve name of the OU/Container.
> >> arrOU = Split(arrContainers(0), "=")
> >> strOU = arrOU(1)
> >>
> >> ' Restore any escaped commas.
> >> strOU = Replace(strOU, Chr(164), "\,")
> >>
> >> Wscript.Echo "User is in OU/Container " & strOU
> >> ========
> >> Again, you can use a Select Case construction to map printers. If you
> >> know
> >> your AD has no DN's with embedded commas or forward slashes you can
> >> eliminate the code that accounts for that, but it doesn't hurt in any
> >> case.
> >>
> >> --
> >> Richard Mueller
> >> MVP Directory Services
> >> Hilltop Lab - http://www.rlmueller.net
> >> --
> >>
> >>
> >>
>
>
>
My System SpecsSystem Spec
Old 07-02-2009   #6 (permalink)
Richard Mueller [MVP]
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

The key for performance is to limit the number of objects bound across the
WAN (in AD). Binding to local objects is not a problem. The example I posted
requires binding to each of the group objects to be tested. 30 such objects
would be a lot.

I retrieve group memberships once and keep them in a dictionary object. This
involves binding just to the user object and retrieving the memberOf
attribute. I must deal with the group DN's, but the code should be fast. For
example:
==========
Option Explicit

Dim objSysInfo, objUser, strUserDN
Dim objGroupList, colstrGroups, strDN
Dim objNetwork

' Bind to current user object.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUserDN)

' Create dictionary object to track groups.
Set objGroupList = CreateObject("Scripting.Dictionary")
objGroupList.CompareMode = vbTextCompare

' Retrieve group memberships (Distinguished Names).
colstrGroups = objUser.memberOf
Select Case TypeName(colstrGroups)
Case "String"
' One group DN in collection.
objGroupList.Add colstrGroups, True
Case "Variant()"
' More than one group DN in collection.
For Each strDN In colstrGroups
objGroupList.Add strDN, True
Next
Case "Empty"
' No group DN's.
End Select

' Map printer per group membership. Repeat for each group.
Set objNetwork = CreateObject("Wscript.Network")
If objGroupList.Exists("cn=Test Group,ou=West,dc=MyDomain,dc=com") Then
objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
End If
=======
If you want to deal with the "pre-Windows 2000" names (sAMAccountName) of
the groups, then you must bind to each group the user is a member of.
However, this should be a much smaller number (hopefully) than the 30 groups
you want to test. Two VBScript examples of functions that tests group
membership by sAMAccountName, and also handle membership due to group
nesting, are linked here:

http://www.rlmueller.net/IsMember2.htm

http://www.rlmueller.net/IsMember4.htm

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--

"Rich" <richjone@xxxxxx> wrote in message
news:8D9FFECF-3220-423C-B740-38D7FE321166@xxxxxx
Quote:

> My scripting knowledge is limited, so please bare with me. How would I do
> this for multiple groups, determining multiple sets of printers? Do I
> just
> keep copying and pasting over and over from the setObjGroup line till the
> end?
>
> or could i just make a huge If or case type statement saying if in group
> Group1 map these printers, if in group Group2 map these printers, etc etc
>
> I understand what your script is doing I think, just not sure how to best
> scale it to probably 30 groups without increasing my users login time
> because
> of a script. It already takes them log enough to log in because of old
> hardware, if it takes longer i might have a mutiny on my hands ;-)
>
> "Richard Mueller [MVP]" wrote:
>
Quote:

>> You would create a group for each printer. Then to test for user
>> membership
>> in the group the code could be similar to:
>> =======
>> Option Explicit
>> Dim objSysInfo, strUserDN, objUser
>> Dim objGroup, objNetwork
>>
>> ' Retrieve DN of current user.
>> Set objSysInfo = CreateObject("ADSystemInfo")
>> strUserDN = objSysInfo.UserName
>>
>> ' Bind to current user object.
>> Set objUser = GetObject("LDAP://" & strUserDN)
>>
>> Set objNetwork = CreateObject("Wscript.Network")
>> ' Bind to group.
>> Set objGroup = GetObject("LDAP://cn=Test
>> Group,ou=West,dc=MyDomain,dc=com")
>>
>> ' Check for membership in the group.
>> If (objGroup.IsMember(objUser.AdsPath) = True) Then
>> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
>> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
>> End If
>> ========
>> I say this method is better because users should be placed in OU's for
>> two
>> purposes. To organize them as you wish in your organization, and to apply
>> the proper Group Policy. It makes things complicated to also use OU's to
>> define printers. You probably have many more printers than logical units
>> in
>> your organization. Groups just have more flexibility.
>>
>> Also, if users can use any computer (or many computers), and computers
>> are
>> fixed (not laptops that roam with the users), it can make sense to map
>> printers according to the group the computer object is a member of. I did
>> this for years. I made my desktop computers member of the appropriate
>> group
>> for the nearest printer. In the logon script I used code similar to:
>> ==========
>> ' Retrieve DN of computer object.
>> Set objSysInfo = CreateObject("ADSystemInfo")
>> strComputerDN = objSysInfo.ComputerName
>>
>> ' Bind to computer object.
>> Set objComputer = GetObject("LDAP://" & strComputerDN)
>>
>> Set objNetwork = CreateObject("Wscript.Network")
>>
>> ' Bind to group.
>> Set objGroup = GetObject("LDAP://cn=Test
>> Group,ou=West,dc=MyDomain,dc=com")
>>
>> ' Check for membership in the group.
>> If (objGroup.IsMember(objComputer.AdsPath) = True) Then
>> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
>> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
>> End If
>> ======
>> There are many methods to check for group membership, but the above is
>> the
>> simplest if you are only concerned with direct membership (you don't care
>> about membership due to group nesting).
>>
>> --
>> Richard Mueller
>> MVP Directory Services
>> Hilltop Lab - http://www.rlmueller.net
>> --
>>
>> "Rich" <richjone@xxxxxx> wrote in message
>> news:78DFCE10-EC54-48CD-9BB7-4EE060B6C7BC@xxxxxx
Quote:

>> >I never thought of doing it based on group membership, I might be able
>> >to
>> >do
>> > it like that since you said it's better. How would I do it based on
>> > group
>> > membership?
>> >
>> > "Richard Mueller [MVP]" wrote:
>> >
>> >> Rich wrote:
>> >>
>> >> >I have users spread out in Active Directory under 20 sub-OU's of a
>> >> >Users
>> >> >OU.
>> >> > What I'd like to do is have a GPO on Users call a script that will
>> >> > map
>> >> > different printers based on what sub-OU the user account is in.
>> >> > Does
>> >> > anyone
>> >> > have a script that will do that? I'm assuming its possible to do.
>> >>
>> >> It's more common to map printers according to group membership. To
>> >> determine
>> >> the parent OU you can use the Parent method of the user object, which
>> >> returns the Distinguished Name of the OU. For example:
>> >> ========
>> >> Option Explicit
>> >> Dim objSysInfo, strUserDN, objUser
>> >> Dim strParentDN, objNetwork
>> >>
>> >> ' Retrieve DN of current user.
>> >> Set objSysInfo = CreateObject("ADSystemInfo")
>> >> strUserDN = objSysInfo.UserName
>> >> ' Escape any forward slash characters.
>> >> strUserDN = Replace(strUserDN, "/", "\/")
>> >>
>> >> ' Bind to current user object.
>> >> Set objUser = GetObject("LDAP://" & strUserDN)
>> >>
>> >> ' Retrieve DN of parent OU/Container.
>> >> strParentDN = objUser.Parent
>> >>
>> >> ' Map printers according to parent OU.
>> >> Set objNetwork = CreateObject("Wscript.Network")
>> >> Select Case LCase(strParentDN)
>> >> Case "ou=west,ou=users,dc=mydomain,dc=com"
>> >> objNetwork.AddWindowsPrinterConnection
>> >> "\\PrintServer1\HPLaser2"
>> >> objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
>> >> Case "ou=east,ou=users,dc=mydomain,dc=com"
>> >> objNetwork.AddWindowsPrinterConnection
>> >> "\\PrintServer2\HPLaser3"
>> >> objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
>> >> End Select
>> >> =======
>> >> Using the DN of the parent OU makes sure the name is unique. You can
>> >> also
>> >> parse for the Relative Distinguished Name (RDN), but that may not be
>> >> unique.
>> >> Code to parse for the RDN could be similar to:
>> >> =========
>> >> Dim objSysInfo, strUserDN, objUser
>> >> Dim strOUPath, arrContainers, arrOU, strOU
>> >>
>> >> ' Retrieve DN of current user.
>> >> Set objSysInfo = CreateObject("ADSystemInfo")
>> >> strUserDN = objSysInfo.UserName
>> >> ' Escape any forward slash characters.
>> >> strUserDN = Replace(strUserDN, "/", "\/")
>> >>
>> >> ' Bind to current user object.
>> >> Set objUser = GetObject("LDAP://" & strUserDN)
>> >>
>> >> ' Retrieve DN of parent OU/Container.
>> >> strOUPath = objUser.Parent
>> >>
>> >> ' Replace any escaped commas with Chr(164).
>> >> strOUPath = Replace(strOUPath, "\,", Chr(164))
>> >>
>> >> ' Parse Parent DN into comma delimited components.
>> >> arrContainers = Split(strOUPath, ",")
>> >>
>> >> ' Parse the first component to retrieve name of the OU/Container.
>> >> arrOU = Split(arrContainers(0), "=")
>> >> strOU = arrOU(1)
>> >>
>> >> ' Restore any escaped commas.
>> >> strOU = Replace(strOU, Chr(164), "\,")
>> >>
>> >> Wscript.Echo "User is in OU/Container " & strOU
>> >> ========
>> >> Again, you can use a Select Case construction to map printers. If you
>> >> know
>> >> your AD has no DN's with embedded commas or forward slashes you can
>> >> eliminate the code that accounts for that, but it doesn't hurt in any
>> >> case.
>> >>
>> >> --
>> >> Richard Mueller
>> >> MVP Directory Services
>> >> Hilltop Lab - http://www.rlmueller.net
>> >> --
>> >>
>> >>
>> >>
>>
>>
>>

My System SpecsSystem Spec
Old 07-04-2009   #7 (permalink)
Mark D. MacLachlan
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

Hi Richard,

We have a similar approach in both favoring using groups to assign
printers. I've noticed though that you seem to prefer to bind to each
group so you can use IsMember where I prefer to bind to the user and
enumerate the groups they are a member of.

http://www.tek-tips.com/faqs.cfm?fid=5798

I'm wondering if you have any opinion on which might perform faster.
I'm thinking that binding to a single object and then iterating through
the array of groups would be quicker but that will really depend on how
many groups a user is a member of. Coding wise, I think using a Select
Case is easier than a whole bunch of If Then statements.

So, I see advantages to both approaches and welcome your expert opinion.

Regards,

Mark D. MacLachlan
My System SpecsSystem Spec
Old 07-04-2009   #8 (permalink)
Richard Mueller [MVP]
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

I often suggest binding to the group object and using the IsMember method
because it is the most straightforward approach. It is not the most
efficient unless you have only one or two groups to check.

The slowest step in any script is binding to objects in AD. Binding to local
objects, like the dictionary object, is much faster. The method that binds
to the fewest objects in AD should be the fastest.

Using the Groups method of the user object is very convenient. You get an
object reference for every group, so you can retrieve any attribute desired.
However, the method must bind to each group object.

Also, using the WinNT provider has the following disadvantages:

1. It is slower (I don't know why).
2. It cannot reveal nested domain group membership.
3. It reveals fewer attributes (although that generally doesn't matter in
logon scripts).

A better approach is to enumerate the memberOf attribute exposed by the LDAP
provider. This is a collection of group DN's (Distinguished Names) the user
belongs to (direct group membership). It does not include the "primary"
group of the user. You must compare the group DN, but you only bind to the
user object, not to the group objects. I keep track of the group DN's in a
dictionary object, so they only need to be enumerated once. If you want to
compare with group sAMAccountName's (pre-Windows 2000 names), use the
NameTranslate object. This is much more efficient than binding to the group
object so you can retrieve sAMAccountName. For information on NameTranslate
see this link:

http://www.rlmueller.net/NameTranslateFAQ.htm

If you enumerate memberOf and need to account for group nesting, you still
need to bind to the group objects. In that case, it might be more efficient
to use ADO to retrieve all group objects where the member attribute matches
the DN of the user. You can retrieve the group DN or sAMAccountName. You can
search with ADO recursively to retrieve all memberships due to nesting. I
have an example linked here:

http://www.rlmueller.net/IsMember7.htm

One query is required for each level of group nesting, but the server
returns all of the information requested in each query in one operation.

Another method if you need to check nested groups is the tokenGroups
attribute of the user. This is a collection of group SID's. It includes all
security group memberships, including the "primary" group and all
memberships due to group nesting. It does not include security groups. The
problem is that you must bind to the corresponding objects to retrieve the
group names. This method is marginally more efficient that enumerating the
memberOf attribute and binding to each group.

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--

"Mark D. MacLachlan" <markdmac@xxxxxx> wrote in message
news:OEKV5JI$JHA.1608@xxxxxx
Quote:

> Hi Richard,
>
> We have a similar approach in both favoring using groups to assign
> printers. I've noticed though that you seem to prefer to bind to each
> group so you can use IsMember where I prefer to bind to the user and
> enumerate the groups they are a member of.
>
> http://www.tek-tips.com/faqs.cfm?fid=5798
>
> I'm wondering if you have any opinion on which might perform faster.
> I'm thinking that binding to a single object and then iterating through
> the array of groups would be quicker but that will really depend on how
> many groups a user is a member of. Coding wise, I think using a Select
> Case is easier than a whole bunch of If Then statements.
>
> So, I see advantages to both approaches and welcome your expert opinion.
>
> Regards,
>
> Mark D. MacLachlan

My System SpecsSystem Spec
Old 07-04-2009   #9 (permalink)
Mark D. MacLachlan
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

Thanks for sharing this Richard. You confirmed a lot of my own
observations.

I'm typically working in the Small/Medium IT space where nested groups
are not an issue with respect to login scripts. Even the few
enterprise customers that I have don't typically nest groups for
printer memberships or departmental groups which is what I would be
using for mapping drives and printers.

When I have an opportunity I'm going to try and get some benchmarks to
compare using memberOf versus binding to the same number of groups and
checking IsMember.

Have a great day and happy 4th of July.

Mark D. MacLachlan
My System SpecsSystem Spec
Old 07-06-2009   #10 (permalink)
Rich
Guest


 
 

Re: Map network printers based on OU user is in within Active Dire

OK, so if I understand right, I want to use the following piece of code, but
then just keep copying and pasting the If statement at the end while tweaking
the CN and printer names, right?

In the IF's parentheses, do I have to put the entire path, or could i just
put the Group name alone? I noticed in your IsMember links it just had the
Group name, which is a little easier on the eyes.

==========
Option Explicit

Dim objSysInfo, objUser, strUserDN
Dim objGroupList, colstrGroups, strDN
Dim objNetwork

' Bind to current user object.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUserDN)

' Create dictionary object to track groups.
Set objGroupList = CreateObject("Scripting.Dictionary")
objGroupList.CompareMode = vbTextCompare

' Retrieve group memberships (Distinguished Names).
colstrGroups = objUser.memberOf
Select Case TypeName(colstrGroups)
Case "String"
' One group DN in collection.
objGroupList.Add colstrGroups, True
Case "Variant()"
' More than one group DN in collection.
For Each strDN In colstrGroups
objGroupList.Add strDN, True
Next
Case "Empty"
' No group DN's.
End Select

' Map printer per group membership. Repeat for each group.
Set objNetwork = CreateObject("Wscript.Network")
If objGroupList.Exists("cn=Test Group,ou=West,dc=MyDomain,dc=com") Then
objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
End If


"Richard Mueller [MVP]" wrote:
Quote:

> The key for performance is to limit the number of objects bound across the
> WAN (in AD). Binding to local objects is not a problem. The example I posted
> requires binding to each of the group objects to be tested. 30 such objects
> would be a lot.
>
> I retrieve group memberships once and keep them in a dictionary object. This
> involves binding just to the user object and retrieving the memberOf
> attribute. I must deal with the group DN's, but the code should be fast. For
> example:
> ==========
> Option Explicit
>
> Dim objSysInfo, objUser, strUserDN
> Dim objGroupList, colstrGroups, strDN
> Dim objNetwork
>
> ' Bind to current user object.
> Set objSysInfo = CreateObject("ADSystemInfo")
> strUserDN = objSysInfo.UserName
> Set objUser = GetObject("LDAP://" & strUserDN)
>
> ' Create dictionary object to track groups.
> Set objGroupList = CreateObject("Scripting.Dictionary")
> objGroupList.CompareMode = vbTextCompare
>
> ' Retrieve group memberships (Distinguished Names).
> colstrGroups = objUser.memberOf
> Select Case TypeName(colstrGroups)
> Case "String"
> ' One group DN in collection.
> objGroupList.Add colstrGroups, True
> Case "Variant()"
> ' More than one group DN in collection.
> For Each strDN In colstrGroups
> objGroupList.Add strDN, True
> Next
> Case "Empty"
> ' No group DN's.
> End Select
>
> ' Map printer per group membership. Repeat for each group.
> Set objNetwork = CreateObject("Wscript.Network")
> If objGroupList.Exists("cn=Test Group,ou=West,dc=MyDomain,dc=com") Then
> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
> End If
> =======
> If you want to deal with the "pre-Windows 2000" names (sAMAccountName) of
> the groups, then you must bind to each group the user is a member of.
> However, this should be a much smaller number (hopefully) than the 30 groups
> you want to test. Two VBScript examples of functions that tests group
> membership by sAMAccountName, and also handle membership due to group
> nesting, are linked here:
>
> http://www.rlmueller.net/IsMember2.htm
>
> http://www.rlmueller.net/IsMember4.htm
>
> --
> Richard Mueller
> MVP Directory Services
> Hilltop Lab - http://www.rlmueller.net
> --
>
> "Rich" <richjone@xxxxxx> wrote in message
> news:8D9FFECF-3220-423C-B740-38D7FE321166@xxxxxx
Quote:

> > My scripting knowledge is limited, so please bare with me. How would I do
> > this for multiple groups, determining multiple sets of printers? Do I
> > just
> > keep copying and pasting over and over from the setObjGroup line till the
> > end?
> >
> > or could i just make a huge If or case type statement saying if in group
> > Group1 map these printers, if in group Group2 map these printers, etc etc
> >
> > I understand what your script is doing I think, just not sure how to best
> > scale it to probably 30 groups without increasing my users login time
> > because
> > of a script. It already takes them log enough to log in because of old
> > hardware, if it takes longer i might have a mutiny on my hands ;-)
> >
> > "Richard Mueller [MVP]" wrote:
> >
Quote:

> >> You would create a group for each printer. Then to test for user
> >> membership
> >> in the group the code could be similar to:
> >> =======
> >> Option Explicit
> >> Dim objSysInfo, strUserDN, objUser
> >> Dim objGroup, objNetwork
> >>
> >> ' Retrieve DN of current user.
> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> strUserDN = objSysInfo.UserName
> >>
> >> ' Bind to current user object.
> >> Set objUser = GetObject("LDAP://" & strUserDN)
> >>
> >> Set objNetwork = CreateObject("Wscript.Network")
> >> ' Bind to group.
> >> Set objGroup = GetObject("LDAP://cn=Test
> >> Group,ou=West,dc=MyDomain,dc=com")
> >>
> >> ' Check for membership in the group.
> >> If (objGroup.IsMember(objUser.AdsPath) = True) Then
> >> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
> >> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
> >> End If
> >> ========
> >> I say this method is better because users should be placed in OU's for
> >> two
> >> purposes. To organize them as you wish in your organization, and to apply
> >> the proper Group Policy. It makes things complicated to also use OU's to
> >> define printers. You probably have many more printers than logical units
> >> in
> >> your organization. Groups just have more flexibility.
> >>
> >> Also, if users can use any computer (or many computers), and computers
> >> are
> >> fixed (not laptops that roam with the users), it can make sense to map
> >> printers according to the group the computer object is a member of. I did
> >> this for years. I made my desktop computers member of the appropriate
> >> group
> >> for the nearest printer. In the logon script I used code similar to:
> >> ==========
> >> ' Retrieve DN of computer object.
> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> strComputerDN = objSysInfo.ComputerName
> >>
> >> ' Bind to computer object.
> >> Set objComputer = GetObject("LDAP://" & strComputerDN)
> >>
> >> Set objNetwork = CreateObject("Wscript.Network")
> >>
> >> ' Bind to group.
> >> Set objGroup = GetObject("LDAP://cn=Test
> >> Group,ou=West,dc=MyDomain,dc=com")
> >>
> >> ' Check for membership in the group.
> >> If (objGroup.IsMember(objComputer.AdsPath) = True) Then
> >> objNetwork.AddWindowsPrinterConnection "\\PrintServer\HPLaser2"
> >> objNetwork.SetDefaultPrinter "\\PrintServer\HPLaser2"
> >> End If
> >> ======
> >> There are many methods to check for group membership, but the above is
> >> the
> >> simplest if you are only concerned with direct membership (you don't care
> >> about membership due to group nesting).
> >>
> >> --
> >> Richard Mueller
> >> MVP Directory Services
> >> Hilltop Lab - http://www.rlmueller.net
> >> --
> >>
> >> "Rich" <richjone@xxxxxx> wrote in message
> >> news:78DFCE10-EC54-48CD-9BB7-4EE060B6C7BC@xxxxxx
> >> >I never thought of doing it based on group membership, I might be able
> >> >to
> >> >do
> >> > it like that since you said it's better. How would I do it based on
> >> > group
> >> > membership?
> >> >
> >> > "Richard Mueller [MVP]" wrote:
> >> >
> >> >> Rich wrote:
> >> >>
> >> >> >I have users spread out in Active Directory under 20 sub-OU's of a
> >> >> >Users
> >> >> >OU.
> >> >> > What I'd like to do is have a GPO on Users call a script that will
> >> >> > map
> >> >> > different printers based on what sub-OU the user account is in.
> >> >> > Does
> >> >> > anyone
> >> >> > have a script that will do that? I'm assuming its possible to do.
> >> >>
> >> >> It's more common to map printers according to group membership. To
> >> >> determine
> >> >> the parent OU you can use the Parent method of the user object, which
> >> >> returns the Distinguished Name of the OU. For example:
> >> >> ========
> >> >> Option Explicit
> >> >> Dim objSysInfo, strUserDN, objUser
> >> >> Dim strParentDN, objNetwork
> >> >>
> >> >> ' Retrieve DN of current user.
> >> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> >> strUserDN = objSysInfo.UserName
> >> >> ' Escape any forward slash characters.
> >> >> strUserDN = Replace(strUserDN, "/", "\/")
> >> >>
> >> >> ' Bind to current user object.
> >> >> Set objUser = GetObject("LDAP://" & strUserDN)
> >> >>
> >> >> ' Retrieve DN of parent OU/Container.
> >> >> strParentDN = objUser.Parent
> >> >>
> >> >> ' Map printers according to parent OU.
> >> >> Set objNetwork = CreateObject("Wscript.Network")
> >> >> Select Case LCase(strParentDN)
> >> >> Case "ou=west,ou=users,dc=mydomain,dc=com"
> >> >> objNetwork.AddWindowsPrinterConnection
> >> >> "\\PrintServer1\HPLaser2"
> >> >> objNetwork.SetDefaultPrinter "\\PrintServer1\HPLaser2"
> >> >> Case "ou=east,ou=users,dc=mydomain,dc=com"
> >> >> objNetwork.AddWindowsPrinterConnection
> >> >> "\\PrintServer2\HPLaser3"
> >> >> objNetwork.SetDefaultPrinter "\\PrintServer2\HPLaser3"
> >> >> End Select
> >> >> =======
> >> >> Using the DN of the parent OU makes sure the name is unique. You can
> >> >> also
> >> >> parse for the Relative Distinguished Name (RDN), but that may not be
> >> >> unique.
> >> >> Code to parse for the RDN could be similar to:
> >> >> =========
> >> >> Dim objSysInfo, strUserDN, objUser
> >> >> Dim strOUPath, arrContainers, arrOU, strOU
> >> >>
> >> >> ' Retrieve DN of current user.
> >> >> Set objSysInfo = CreateObject("ADSystemInfo")
> >> >> strUserDN = objSysInfo.UserName
> >> >> ' Escape any forward slash characters.
> >> >> strUserDN = Replace(strUserDN, "/", "\/")
> >> >>
> >> >> ' Bind to current user object.
> >> >> Set objUser = GetObject("LDAP://" & strUserDN)
> >> >>
> >> >> ' Retrieve DN of parent OU/Container.
> >> >> strOUPath = objUser.Parent
> >> >>
> >> >> ' Replace any escaped commas with Chr(164).
> >> >> strOUPath = Replace(strOUPath, "\,", Chr(164))
> >> >>
> >> >> ' Parse Parent DN into comma delimited components.
> >> >> arrContainers = Split(strOUPath, ",")
> >> >>
> >> >> ' Parse the first component to retrieve name of the OU/Container.
> >> >> arrOU = Split(arrContainers(0), "=")
> >> >> strOU = arrOU(1)
> >> >>
> >> >> ' Restore any escaped commas.
> >> >> strOU = Replace(strOU, Chr(164), "\,")
> >> >>
> >> >> Wscript.Echo "User is in OU/Container " & strOU
> >> >> ========
> >> >> Again, you can use a Select Case construction to map printers. If you
> >> >> know
> >> >> your AD has no DN's with embedded commas or forward slashes you can
> >> >> eliminate the code that accounts for that, but it doesn't hurt in any
> >> >> case.
> >> >>
> >> >> --
> >> >> Richard Mueller
> >> >> MVP Directory Services
> >> >> Hilltop Lab - http://www.rlmueller.net
> >> >> --
> >> >>
> >> >>
> >> >>
> >>
> >>
> >>
>
>
>
My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
HELP! Vista Business - Active Director Vista General
Script to query user information based upon group membership VB Script
Still can't consistently network between XP/Vista based PCs Vista networking & sharing
Attempt to Network Vista Home on Domain Based Network (W2K -Server Vista networking & sharing
Belkin Web-based User Interface access issue following Vista upgra Vista networking & sharing


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46