Previous Page
Next Page

Deploying Logon Scripts

Perhaps the simplest way to implement a logon script is to modify the Logon Script User attribute. Although you can assign logon scripts to users by using the graphical user interface (GUI), you can also do this easily by using the scriptpath Active Directory attribute of the User object. I prefer, however, to use Group Policy to assign the logon script to users. However you choose to assign logon scripts to your users, once you write the script, this script will need to be saved in the Sysvol share in the Scripts directory as seen in Figure 16-1.

Figure 16-1. Sysvol share in Active Directory; logon scripts and accessory scripts


If you do this, you can link the script to multiple Group Policy Objects (GPOs). You could, of course, also save the logon script within the actual GPO itself. If you choose to save it in this way, you will not be able to reuse the script with other GPOs. In fact, you could end up deleting the script if you delete the GPO that is hosting the script. Linking a logon script to a GPO is illustrated in Figure 16-2.

Figure 16-2. GPO logon script; assign the logon script to the User object in Group Policy


So what does a VBScript logon script look like? The following script, LogonScript.vbs, is similar to many logon scripts I've used with customers in the past. It has several advantages over the old-fashioned batch files that many of you grew up with. We'll discuss these advantages as we examine each section that makes up LogonScript.vbs.

Note

The logon script below will fail if the user is a member of only one group. There are several ways to fix this problem ... the simplest is to simply use On Error Resume Next. Another way would be to use an error handler, and then if it fails the first time, come back and repeat the line without the Join function.


LogonScript.vbs

Option Explicit
Dim fServer
Dim pServer
Dim home
Dim wshNet
Dim ADSysInfo
Dim CurrentUser
Dim strGroups
Dim GroupMember
Dim a,b,c

Const HR = "cn=hrgroup"
Const MARKETING = "cn=marketinggroup"
Const SALES = "cn=salesgroup"

fServer = "\\london"
pServer = "\\london"
home = "\\london\users"
Set wshNet = CreateObject("WScript.Network")

Set ADSysInfo = CreateObject("ADSystemInfo")
Set CurrentUser = GetObject("LDAP://" & ADSysInfo.UserName)
strGroups = LCase(Join(CurrentUser.MemberOf))

wshNet.MapNetworkDrive "h:", fServer & "\Users\" & wshNet.UserName
WScript.Echo(wshNet.Username & " " & strgroups)

Select Case GroupMember
case a = InStr(strGroups, HR)
  HRsub
case b = InStr(strGroups, SALES)
SalesSub
case c = InStr(strGroups, MARKETING)
  MarketingSub
End Select

' *** departmental subs are below *****
Sub HRsub
wshNet.MapNetworkDrive "g:",fServer & "\Hr"
  wshNet.AddWindowsPrinterConnection pServer &"\HrPrinter"
  wshNet.SetDefaultPrinter pServer & "\HrPrinter"
  subRunScript
End Sub

Sub SalesSub
  wshNet.MapNetworkDrive "s:", fServer & "\Sales"
  wshNet.AddWindowsPrinterConnection pServer & "\SalesPrinter"
  wshNet.SetDefaultPrinter pServer & "\SalesPrinter"
End Sub

Sub MarketingSub
wshNet.MapNetworkDrive "m:", fServer & "\Marketing"
  wshNet.AddWindowsPrinterConnection pServer & "\MarketingPrinter"
  wshNet.SetDefaultPrinter pServer & "\MarketingPrinter"
End Sub

Sub subRunScript
Dim objShell
Set objShell = CreateObject("wscript.shell")
objShell.run ("CheckForHotFix.vbs")
End Sub

Header Information

The Header information section of LogonScript.vbs includes the Option Explicit command and the declaration of several variables.

Tip

You don't use On Error Resume Next in logon scripts because if the logon script fails, you want to hear from your user community immediately. You don't want to suppress error messages or risk mapping only a few of the drives that the users need to be able to perform their work. I've seen situations in which the logon script messed up drive mappings for a group of users, and these users had no idea where their data was stored. We wound up having to reproduce the error in a lab to determine what drives had been mapped for which user so that we could find the work the users had "lost." Once this was done, we removed error suppression on the logon script, and although doing this might have resulted in a few more help desk calls, it vastly simplified the consequences when the logon script failed.


Eleven variables are used in LogonScript.vbs. They are listed in Table 16-3.

Table 16-3. LogonScript.vbs Variables

Variable

Use

fServer

Holds the name of the file server. Used when mapping home directory for the user.

pServer

Holds name of the print server. Used when mapping printers for the user.

Home

Holds the relative path of the users' home directory share. This variable also could be expanded by using site information to point the closed file server to the users.

wshNet

Holds the object that comes back when you create an instance of WScript.Network. You use this to allow the mapping of drives and printers.

ADSysInfo

Holds the object that comes back when you create an instance of ADSystemInfo. This allows you to obtain current user information.

CurrentUser

Holds a connection into Active Directory using the Lightweight Directory Access Protocol (LDAP) provider.

strGroups

Holds a list of all the groups of which the user is a member.

GroupMember

Used by the Select Case statement to hold the value of the group membership.

a,b,c

Used with Select Case to determine case.


Tip

Depending on how you decide to document your scripts, creating a table of variables can be a powerful reference tool. I know some Internet administrators who print out all their production scripts and store them in a binder along with their definitive software library (DSL). Others store backup copies of production scripts on a network share and use remarks to document the scripts. Even if you do not need a variable table for script documentation, you might find that creating one is sometimes helpful as a reference when writing the scriptit forces you to think about the script flow, and in a long script, it is easier to work with a table than scrolling back up to the Header information section of the script. This is a good habit to develop if you program in C# or Microsoft Visual Basic .NET as well.


Reference Information

In addition to defining the variables listed in the Header information section of the script, you also define some constants. The three constants hold the name of the groups that are searched for by using the InStr command. In this example, the group memberships are HrGroup, MarketingGroup, and SalesGroup. You assign the "cn=" version of the name to the constants called HR, Marketing, and Sales. You do this because when you perform the query for the group memberships, the string of data returned will include the full LDAP name of the groups. However, to make the code easier to type and understand and thus easier to work with, you assign the longer names to constants. The resultant code looks like the following:

Const HR = "cn=hrgroup"
Const MARKETING = "cn=marketinggroup"
Const SALES = "cn=salesgroup"

fServer = "\\london"
pServer = "\\london"
home = "\\london\users"

The remainder of the Reference information section appears in the code that follows. You use a variable, fServer, to hold the name of the file server. This makes it easy to change the script if you move the shared directories to other servers. If you did not use this variable, the drive mappings would use the hardcoded Universal Naming Convention (UNC) path to a specific server share. This means that if the data got moved to a different server, the logon script would need to be modified in several places.

All the users' home directories are in a shared directory called Users. If you move the share to a different location, you will need to modify the home = "\\london\users" line in the script. Changing this line is easier than making a change in the Home Folder field on the Profile tab in Active Directory Users And Computers (ADUC). Change one line in the logon script, or make thousands of changes via the GUI in ADUCit seems to be a relatively painless choice!

Quick Check

Q.

What are three ways of assigning a logon script to a user?

A.

Three ways of assigning a logon script to a user are via the GUI interface by using Active Directory Users And Computers, via VBScript by using the ScriptPath property, or by using Group Policy.

Q.

What are three common activities performed by logon scripts?

A.

Three common activities performed by logon scripts are mapping to network shares, mapping to network printers, and setting default printers for users.


Using the WshNetwork Class

The next order of business is wiring up three connections to turn on the power of VBScript in our logon script. The first of these connections is used to hold the object that comes back from creating an instance of the WScript.Network class. You use WScript.Network to create an object that is called WshNetwork. WshNetwork enables you to connect to and disconnect from network shares and network printers. In addition, we can use WshNetwork to map or remove network shares or to access information about a user on a network. This said, you might be asking yourself why we decided to use ADSystemInfo to obtain the user name. The reason is that the user name coming from WshNetwork is a single-label name (for example, Bob). But to query Active Directory to obtain all your group memberships, you need the distinguished name (for example, a name like cn=bob, ou=LabOU, dc=nwtraders, dc=msft.) You can use the distinguished name to make an LDAP binding and then to query all the information you need to obtain for the logon script.

After you create an instance of WshNetwork, you are ready to connect to the IADsADSystemInfo interface so that you can get information about the local computer and local user.

After you have an object providing access to the ADSystemInfo interface, you use the UserName command to obtain the fully qualified local user name, and then combine that with the LDAP provider and make a connection into Active Directory. The object that comes back from Active Directory is called CurrentUser. You have now wired up all the connections necessary to get the logon script up and running.

You do need to define one more variablea list of groups of which the current user is a member. To do this, you use the MemberOf command. The problem is that the MemberOf command will return with an array. In the following section, we will see how to address this problem.

Using the Join Function

Although arrays are useful, dealing with an array will make your script a bit more complicatedin fact, because you are interested only in the presence of a particular string sequence, you don't need an array at all. For assistance in dealing with the array, use the VBScript Join function. The Join function returns a string that is created by putting together (that is, joining) the data contained in the array elements. In this way, you can easily use the InStr command to search the string for the presence of your group membership items. You can see an example of using the Join function in the Join.vbs script, which you'll examine in a moment.

Notice that you begin the Join.vbs script by declaring a five-element array. You then assign a value to each element in the array. On the next-to-last line, you use the Join function to pull together all the elements of the array, which is called MyArray. The advantage here is using an intermediate variable to hold the array, and then using another variable to hold the string returned from the Join function. This adds a lot of flexibility to your script. You assign the string that is returned from the Join function to a variable called MyString. Because you now have a string that contains all the elements of the array, you can use WScript.Echo to display the value of MyString.

Join.vbs

Option Explicit
Dim MyString
Dim MyArray(4)
MyArray(0) = "Mr."
MyArray(1) = "Sam"
MyArray(2) = "Spade,"
MyArray(3) = "Private"
MyArray(4) = "Eye"
MyString = Join(MyArray)
WScript.Echo(MyString)


Worker Information

The Worker information section of LogonScript.vbs comprises a single Select Case statement. The Select Case statement is interesting because you are doing something new. GroupMember is a variable used to evaluate the group membership. In reality, this variable is just a placeholder, because you don't use it anywhere else in the script. Each case is evaluated by InStr and the corresponding subroutine is selected. The nice part of this Select Case statement happens on the other side of the equal signs. Instead of performing a simple match, you're adding a higher level of intelligence to the script and are requiring the Select Case statement to use the InStr function to search the string data contained in the variable strGroups. Each case is therefore tested to see whether the string represented by each constant is found in strGroups. When a match is found, the script jumps to the appropriate subroutine. This type of statement makes the Worker information section extremely easy to read and understand.

Select Case GroupMember
   case a = InStr(strGroups, HR)
  HRsub
   case b = InStr(strGroups, SALES)
         SalesSub
   case c = InStr(strGroups, MARKETING)
  MarketingSub
End Select


Previous Page
Next Page