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.
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.
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.
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"
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.
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. |
|