Previous Section Table of Contents Next Section

NT and Active Directory Logon Scripts

The first example script works in either an Active Directory (AD) or NT domain environment. It includes a number of common logon script tasks.

NOTE

One thing to be careful of: Windows 9x scripts actually execute before the operating system finishes the user logon process. As a result, the technique I use to retrieve the current user's name won't always work properly. There's no pretty workaround for this; I'll show you one example of how to make your script essentially sit and wait until Windows finishes and the user name becomes available.


graphics/arrow.gif Logon Script One

Listing 29.1 shows the script code. I've included comments to help identify each task, so that you can easily break this apart and reuse various bits in your own scripts.

Listing 29.1. Logon1.vbs. This script includes most common logon script tasks.

' sample logon script



' first let's create the objects we'll be using

dim objShell, objNetwork

set objShell = WScript.CreateObject("WScript.Shell")

set objNetwork = WScript.CreateObject("WScript.Network")



' let's display a welcome message

dim strDomain, strUser

strDomain = objNetwork.UserDomain

strUser = objNetwork.UserName

msgbox "Welcome to the " & strDomain & ", " & strUser & "!"





'we'll map the Z: drive to a network location

objNetwork.MapNetworkDrive "Z:", "\\Server\Share"





'let's connect to a network printer and make it

' the default - we'll capture LPT2:

objNetwork.AddPrinterConnection "LPT2", "\\Server\Print1"





'connect a second printer without capturing a printer port

objNetwork.AddWindowsPrinterConnection _

"\\server\print2", "Lexmark Optra S 1650"





'let's make that the default printer

objNetwork.SetDefaultPrinter "\\Server\Print2"





'now let's see if this fellow is a Domain Admin

dim objAdmins, user, IsMember

IsMember = False

set objAdmins = GetObject("WinNT://Domain1/Domain Admins")

for each user in objAdmins.members

 if user.name = strUser then

  IsMember = True

 end if

next



'if user is Domain Admin map the Y: drive

if IsMember = true then

 objNetwork.MapNetworkDrive "Y:", "\\Server\C$"

end if

You obviously need to adjust server names, domain names, and so forth to make this run in your environment. However, rather than getting this script to run in your environment, I recommend pulling out the pieces you like and building your own script from scratch.

graphics/arrow.gif Logon Script One-Explained

I begin by creating the various objects I need to use and assigning them to variables. If you break apart this script, be sure to pull out the appropriate object creation statements.


' sample logon script



' first let's create the objects we'll be using

dim objShell, objNetwork



set objShell = WScript.CreateObject("WScript.Shell")

set objNetwork = WScript.CreateObject("WScript.Network")

I use MsgBox() to display a friendly welcome message that includes the domain name and user name.


' let's display a welcome message

dim strDomain, strUser

strDomain = objNetwork.UserDomain

strUser = objNetwork.UserName

msgbox "Welcome to the " & strDomain & ", " & strUser & "!"

I mentioned earlier that this doesn't work so well on Windows 9x computers, because UserName isn't available right away. If you need to ensure that this will work properly on 9x machines, try adding the following modification.


' let's display a welcome message

dim strDomain, strUser

Do Until objNetwork.UserName <> ""

 WScript.Sleep(5000)

Loop

strDomain = objNetwork.UserDomain

strUser = objNetwork.UserName

msgbox "Welcome to the " & strDomain & ", " & strUser & "!"

This modification (shown in boldface) has the script sleep in five-second increments, and then check to see if Windows has finished logging on and populated the UserName property of the Network objects.

Moving on, I next map a drive to a network location. Easily the single most common logon script task, this is accomplished in just one line of code.


'we'll map the Z: drive to a network location

objNetwork.MapNetworkDrive "Z:", "\\Server\Share"

Next, I capture the LPT2 port to a network printer. This is less common nowadays, because so few of us are running old DOS applications that require captured printer ports, but here it is in case you need it.


'let's connect to a network printer - we'll capture LPT2:

objNetwork.AddPrinterConnection "LPT2", "\\Server\Print1"

Far more common is the need to map a network printer. Note that this only works if Windows "Point and Print" is enabled. In other words, if you run this command and the print server doesn't have the appropriate printer drivers for your client, the command fails. Generally, NT-based clients printing to same-generation NT-based servers (such as XP printing to Windows 2000 or 2003) use the server's printer drivers, and this command works fine.

The second parameter defines the name of the printer as you want it to appear in the client's Printers and Faxes folder.


'connect a second printer without capturing a printer port

objNetwork.AddWindowsPrinterConnection "\\server\print2", _

 "Lexmark Optra S 1650"

You can make a mapped printer the default, as shown here. Just specify the UNC. Note that the printer should already be mapped for this to work best.


'let's make that the default printer

objNetwork.SetDefaultPrinter "\\Server\Print2"

Checking for group membership is the roughest thing a logon script has to do. I start by defining a variable, IsMember, and setting it to False. Then, I use ADSI to query for the domain's Domain Admins group.


'now let's see if this fellow is a Domain Admin

dim objAdmins, user, IsMember

IsMember = False

set objAdmins = GetObject("WinNT://Domain1/Domain Admins")

Next, I run through each member of the group to see if the current user is a member of the group. If I find the current user in the group, I set IsMember to True.


for each user in objAdmins.members

 if user.name = strUser then

  IsMember = True

 end if

next

The preceding routine is just a tad inefficient; after I locate the current user in the group, there's no need to continue checking other members. The routine can be made just a bit more efficient by adding one line, shown here in boldface.


for each user in objAdmins.members

 if user.name = strUser then

  IsMember = True

  Exit Sub

 end if

next

My last action is to map a drive to a server's administrative share if the user is, in fact, a domain administrator. Checking for membership first ensures that this command runs without error, because only domain admins (by default) have permission to server administrative shares.


'if user is Domain Admin map the Y: drive

if IsMember = true then

      objNetwork.MapNetworkDrive "Y:", "\\Server\C$"

end if

One thing this script doesn't accommodate is nested group membership. For example, if the user is a member of a group, and the group is a member of Domain Admins, this script doesn't pick up on that. Checking for nested group membership is a bit more complex; for scripts like this, I usually don't worry about it because for security reasons, I try to avoid including other groups in Domain Admins.

graphics/arrow.gif Logon Script Two

Listing 29.2 shows another logon script that runs in any domain environment. This one performs a few more advanced tasks, such as writing to the registry and running a command-line utility. This script also checks to see if it was run from Cscript.exe (rather than WScript.exe), and exits if it wasn't.

Listing 29.2. Logon2.vbs. This logon script performs more advanced logon tasks.

Dim oShell

Dim oNetwork

Set oShell  = WScript.CreateObject ("WScript.shell")

Set oNetwork = WScript.CreateObject("WScript.Network")



'ensure this was run by using Cscript

Dim oRegExp, bIsCScript

Set oRegExp = New RegExp

oRegExp.IgnoreCase  = true

oRegExp.Pattern = "cscript.exe$"

bIsCScript = oRegExp.Test(WScript.FullName)

Set oRegExp = Nothing

If Not bIsCScript() Then

  Wscript.echo WScript.FullName & _

   " must be run with CScript."

  Wscript.Quit

End If



'run command line

oShell.Run "NET TIME /RTSDOMAIN:BRAINCORE /SET"



'write registry key

oShell.RegWrite "HKLM\Software\Company" & _

 "\Software\Key\Value", 1, "REG_DWORD"

graphics/arrow.gif Logon Script Two-Explained

As usual, I start by declaring variables and creating the objects I'll use in the script.


Dim oShell

Dim oNetwork



Set oShell  = WScript.CreateObject ("WScript.shell")

Set oNetwork = WScript.CreateObject("WScript.Network")

The next bit of code uses a regular expression to see if the script was executed via Cscript.exe. I start by creating the regular expression object.


'ensure this was run by using  Cscript

Dim oRegExp, bIsCScript

Set oRegExp = New RegExp

Next, I tell it to ignore upper- and lower-case differences in the comparison I'll have it make, and I tell it that I'm looking for a string that starts with "cscript.exe" and ends with anything.


oRegExp.IgnoreCase  = true

oRegExp.Pattern = "cscript.exe$"

I test the comparison pattern against the full name of the currently running script. If the result comes back empty (Nothing), I know the script wasn't run with Cscript.exe, so I display a message and quit. This is a useful technique if you want to ensure command-line output formatting or some other feature unique to Cscript.exe.


bIsCScript = oRegExp.Test(WScript.FullName)

Set oRegExp = Nothing

If Not bIsCScript() Then

  Wscript.echo WScript.FullName & _

   " must be run with CScript."

  Wscript.Quit

End If

Next, I have the script execute a command-line utility. In this case, it's the NET TIME command, used to set the local computer's clock. This demonstrates how to run external command-line utilities from within a script. This is also a good reason to run the script from Cscript, so that a new command-line window doesn't pop open just to execute this command, which is what would happen if you used WScript.


'run command line

oShell.Run "NET TIME /RTSDOMAIN:BRAINCORE /SET"

Finally, I write a registry value. You could also write operating system values to force SMB signing or other features.


'write registry key

oShell.RegWrite "HKLM\Software\Company" & _

 "\Software\Key\Value", 1, "REG_DWORD"

This script is another example of the flexibility VBScript can bring to your logon scripts.

Calling VBScript Logon Scripts in NT Domains

NT wasn't built to understand VBScript, and its ability to define logon scripts is pretty much limited to executable (EXE) and batch (BAT) files. Fortunately, those are enough to get VBScript scripts up and running.

One option is to define the logon script for your users as Wscript.exe scriptname.vbs, calling WScript.exe directly and passing the name of the script to run. That technique has problems with some clients, however, because they aren't expecting a space in the logon script name.

Another technique is to create a simple batch file that launches WScript.exe and the appropriate logon script. You can then define that batch file as users' actual logon script, and it'll get your code up and running appropriately.

Keep in mind that all users expected to run your script must have the Windows Script Host (WSH) installed, and that the latest version (5.6 as of this writing) is preferred.


    Previous Section Table of Contents Next Section