Hack 53 Add Printers Based on Name of Computer

figs/expert.gif figs/hack53.gif

Here's a logon script you can use to solve a complicated problem in printer management: performing a logon task based on the name of the computer being logged into.

In various forums, I have noticed questions regarding how to perform tasks at logon based on the name of the computer that the user is logging into. In my environment (a small community college), we thought we could have fewer servers and reduce network traffic by configuring all our computers to use TCP/IP printing. This worked out pretty well for a while, but we discovered a few drawbacks of using TCP/IP printing. For example, there is no control over excessive printing and it is not possible to track costs back to a user. Also, it is difficult to update systems when printers get replaced

We soon split our thinking and were able to switch 99% of our student computers to print through a few servers. To assist us with our print-management needs, we purchased Print Manager Plus (http://www.printmanagerplus.com). Print Manager Plus has many benefits for my environment. We are an educational institution that has a number of open-use areas where students and the public can use our computers. We do not track printing costs back to users, and we were experiencing a rising cost of print supplies due to misuse of our printers. The implementation of Print Manager Plus allowed us to put controls in place that limit abuse in the following ways:

  • The user is able to print only 8 pages at a time. If the user's document is 10 pages long, he must print pages 1-8, then 9-10.

  • There is a limit on the file size of the print job. The user is unable to print a document that is larger than 15MB when it arrives at the server.

Print Manager Plus has the ability to inform the user when he exceeds the defined limits. I have customized the messages sent from Print Manager Plus to the user so that they present him with options on how to print the document in question.

Server-based printers, however, created a few headaches of their own. In particular, any room is pretty much fair game for us to use when we provide training to not only our students, but also our faculty and staff. We needed a way to set the right printer on any given computer for any user who logs on. Also, we wanted to use one logon script for all users in any domain.

We also had a Windows 2000 Terminal Server available but had not made good use of it until recently. The original thinking was to install a bunch of printers on it and trust users to select the appropriate printer before hitting the print button. We soon had calls asking, "What are all these documents coming out of my printer?"

Anyway, I thought about this awhile and decided that the best approach would be to add the printers based on the name of the computer. We have a standard naming convention in use that made this task possible.

This hack contains the code that I came up with. The code should be pretty readable by itself, but I'll spend some time briefly discussing some of its more major parts.

The Code

To get the code for the script, I suggest downloading the Logon.vbs file from the O'Reilly web site (http://www.oreilly.com/catalog/winsvrhks/), because it's too long to type from scratch. This version of the script was tested on Windows 2000 Service Pack 2 running Internet Explorer 6 Service Pack 1 with Microsoft Windows Script v5.6. It was also tested on Windows XP Professional participating in a small Active Directory domain.

I have had a variation of this script in production for a long time now with great success. But, as always, either the differences in your environment or something I missed in editing the script for this hack might cause things behave unexpectedly.


Depending on your environment, the code requires:

  • A recent version of Internet Explorer (http://www.microsoft.com/windows/ie/default.asp).

  • Windows Script 5.6 for Windows 98/ME/NT (http://www.microsoft.com/downloads/details.aspx?FamilyID=0a8a18f6-249c-4a72-bfcf-fc6af26dc390)

  • Windows Script for 2000/XP (http://www.microsoft.com/downloads/details.aspx?FamilyID=c717d943-7e4b-4622-86eb-95a22b832caa)

  • Active Directory Client Extensions for Windows 9x, ME or NT4 (http://www.microsoft.com/windows2000/techinfo/howitworks/activedirectory/adsilinks.asp).

For more information on using Internet Explorer for status messages, see "Using an IE Window to Display Progress" (http://www.myitforum.com/articles/11/view.asp?id=3489), "VBScript Forms (Part 1): Using Internet Explorer for Data Input/Output Forms" (http://www.myitforum.com/articles/11/view.asp?id=4390), and "Using IE to Browse for Files" (http://www.myitforum.com/articles/11/view.asp?id=4229).

Perform initial tasks

This section sets up the basics of the script. In this script, I also call a few subroutines/functions (listed further in later sections) that either gather information or perform my required tasks. I like using subroutines and functions, because it makes my code reusable or easily stored in a code library for future coding endeavors. This section accomplishes the following major tasks:

  • Call a subroutine that gathers basic system information

  • Exit the script if user is logged on locally to the server

  • Call subroutines to gather group memberships

The script also performs other tasks, as discussed in comments throughout the code.

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' File:     Logon.vbs

' Updated:  April 2003

' Version:  2.1

' Author:   Dan Thomson, myITforum.com columnist

'           I can be contacted at dethomson@hotmail.com

'

' Usage:

'           This script can be directly assigned as a logon script for

'           Windows 2000 or greater clients. For older systems, this

'           script will need to be called from a logon batch file.

'

' Input:

'

' Requirements:

'           Win 9x, ME or NT 4:

'           - Active Directory Client Extensions

'             http://www.microsoft.com/windows2000/techinfo/howitworks/

'             activedirectory/adsilinks.asp

'           - Windows Script

'             http://msdn.microsoft.com/library/default.asp?url=/downloads

'             /list/webdev.asp

'           - A recent version of Internet Explorer

'

' Notes:

'           Tested on Windows 2000 Professional running Windows Script v5.6

'           and participating in an AD domain

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''



On Error Resume Next



''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

' Define Variables and Constants

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''



Dim objFileSys

Dim objIntExplorer

Dim objWshNetwork

Dim objWshShell

Dim strDomain           'Domain of the user

Dim strHomePage         'Homepage to be set for user

Dim strLogonPath        'Path to location from where the script is running

Dim strOSProdType       'OS Product type (WinNT, LanmanNT, ServerNT)

Dim strWorkstation      'Local Computer Name

Dim strUserGroups       'List of groups the user is a meber of

Dim intCounter          'General counter



Const UseNTServer = 0   'Sets whether this script runs when logging on locally

                        'to Windows Servers.

                        'Values are: 1 (Yes) OR 0 (No)



'Initialize common scripting objects

Set objFileSys    = CreateObject( "Scripting.FileSystemObject" )

Set objWshNetwork = CreateObject( "WScript.Network" )

Set objWshShell   = CreateObject( "WScript.Shell" )



'Pause script until user is fully logged on (applies only to Win 9x or ME)

'This will timeout after 10 seconds

strUser = ""

intCounter = 0

Do

  strUserID = objWshNetwork.Username

  intCounter = intCounter + 1

  Wscript.Sleep 500

Loop Until strUserID <> "" OR intCounter > 20



'Check for error getting username

If strUserID = "" Then

  objWshShell.Popup "Logon script failed - Contact the Helpdesk @ x 345", , _

    "Logon script", 48

  Call Cleanup

End If



'Setup IE for use as a status message window

Call SetupIE



'Display welcome message

Call UserPrompt ("Welcome " & strUserID)



'Add horizontal line as a 'break'

objIntExplorer.Document.WriteLn("<hr style=""width:100%""></hr>")



'Gather some basic system info

Call GetSystemInfo



If IsTerminalServerSession <> True Then

  'Exit if we are logging on locally to a server and the 

  'script is set to NOT run on servers

  IF UseNTServer = 0 AND (strOSProdType = "LanmanNT" OR strOSProdType = "ServerNT") Then

    objWshShell.Popup "Windows Server - Exiting Logon Script!", 10, _

    "Logon to " & strDomain, 16

    Call CleanUp

  End if

End If



'Get group memberships

strUserGroups = ""

Call GetLocalGroupMembership

Call GetGlobalGroupMembership



''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Map drives, add shared printers and set default homepage

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Determining workstation settings

This section determines which settings should be applied to the workstation, based on the name of the workstation. Our environment has a nice naming convention: the building, room number, and station number are identified in the name. For example, the name Blg4Rm105-03 identifies a computer as being station 3, located in building 4, room 105. To determine which mappings get assigned to a computer, all I have to do is base my criteria on everything on the left of the dash (-).

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Part A

' This section performs actions based on computer name

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''



'The left side of the computer name contains building and room information

If Instr( 1, strWorkstation, "-", 1) > 0 Then

  strWorkstation = _

    Left( strWorkstation, ( Instr( 1, strWorkstation, "-", 1)))

End If



Select Case UCase( strWorkstation )



  Case "BLD1RM101-"

    Call MapDrive ("U:", "MyShareSvr1", "MyShare1")

    Call AddPrinter ("Mydomain2", "MyPrtSvr2", "Bld1Rm101-HP4050")

    objWshNetwork.SetDefaultPrinter "\\MyPrtSvr2\Bld1Rm101-HP4050"

    strHomePage = "http://www.chesapeake.edu/academic_info/ " & _

    "acad_computing.asp"

  Case "BLD1RM202-"

    Call MapDrive ("U:", "MyShareSvr2", "MyShare2")

    Call AddPrinter ("Mydomain1", "MyPrtSvr1", "Bld1Rm202-HP4000")

    objWshNetwork.SetDefaultPrinter "\\MyPrtSvr1\Bld1Rm202-HP4000"

    strHomePage = "http://www.chesapeake.edu/library/default.asp"

  Case "BLD3RM104-"

    'This room uses TCP/IP printing instead of a print server. 

    'Only set homepage

    strHomePage = "http://www.chesapeake.edu/writing/wchome.htm"

  Case Else



End Select

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Adding mappings based on group membership

Adding mappings based upon the computer name is cool. However, there will always be a need to perform tasks based on specific group membership. This section takes care of such tasks.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Part B

' This section performs actions based on group membership

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''



If InGroup( "ShareForStaff" ) Then

  Call MapDrive ("X:", "StaffSvr1", "StaffShare1")

  strHomePage = "http://www.chesapeake.edu/generalinfo/cambridge.asp"

End If



If InGroup( "ShareForStudents" ) Then

  Call MapDrive ("Y:", "StudentSvr1", "StudentShare1")

  strHomePage = "http://www.chesapeake.edu"

End If



''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

' End section

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Setting the IE home page and final message

This section sets the IE home page (if specified), starts SMSls.bat, and posts a final message to the user. The script tests to determine if the user is a member of the Domain Admins or DoNotInstallSMS groups. If the user is a member of either of these groups, SMSls.bat is skipped. This is helpful if you want to get in quick to do a small task or to keep SMS off some of your more persnickety users' computers.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Set default homepage

If strHomePage <> "" Then

  Err.Clear

  objWshShell.RegWrite _

    "HKCU\Software\Microsoft\Internet Explorer\Main\Start Page", strHomePage

  If Err = 0 Then Call UserPrompt ("Set Internet home page to " & strHomePage)

End If



'Start SMSls.bat

'Do not run if a member of the Domain Administrators

'or in the global group DoNotInstallSMS

If InGroup("Domain Admins") OR InGroup("DoNotInstallSMS") Then

  Call UserPrompt ("Skipping SMSLS.BAT")

Else

  objWshShell.Run "%COMSPEC% /c " & strLogonPath & "\smsls.bat", 0, False

End If



'Add horizontal line as a 'break'

objIntExplorer.Document.WriteLn("<hr style=""width:100%""></hr>")



'Inform user that logon process is done

Call UserPrompt ("Finished network logon processes")



'Wait 10 seconds

Wscript.Sleep (10000)



'Close Internet Explorer

objIntExplorer.Quit( )



Call Cleanup

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

That's the end of the first major section of the script. The following subsections list and explain the various subroutines and functions.

Connecting to a shared network printer

The following routine is where the printer mapping occurs. It first verifies that the share is accessible and creates the mapping. If the share is not accessible or is not a valid print share, the user will be prompted with an error message that lets her know she should call the help desk.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      AddPrinter

'

' Purpose:  Connect to shared network printer

'

' Input:

'           strPrtServerDomain  Domain in which print server is a member

'           strPrtServer        Name of print server

'           strPrtShare         Share name of printer

'

' Output:

'

' Usage:

'           Call AddPrinter ("Mydomain2", "MyPrtSvr2", "Bld1Rm101-HP4050")

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub AddPrinter(strPrtServerDomain, strPrtServer, strPrtShare)



  On Error Resume Next



  Dim strPrtPath    'Full path to printer share

  Dim objPrinter    'Object reference to printer

  Dim strMsg        'Message output to user

  Dim blnError      'True / False error condition



  blnError = False



  'Build path to printer share

  strPrtPath = "\\" & strPrtServer & "\" & strPrtShare



  'Test to see if shared printer exists.

  'Proceed if yes, set error condition msg if no.

  Set objPrinter = GetObject _

    ("WinNT://" & strPrtServerDomain & "/" & strPrtServer & "/" & _ 

    strPrtShare)

  If IsObject( objPrinter ) AND _

  (objPrinter.Name <> "" AND objPrinter.Class = "PrintQueue") Then



     'Different mapping techniques depending on OS version

     If objWshShell.ExpandEnvironmentStrings( "%OS%" ) = "Windows_NT" Then

       Err.Clear

       'Map printer

       objWshNetwork.AddWindowsPrinterConnection strPrtPath

     Else

       'Mapping printers for Win9x & ME is a pain and unreliable.

     End If



  Else

    blnError = True

  End IF



  'Check error condition and output appropriate user message

  If Err <> 0 OR blnError = True Then

    strMsg = "Unable to connect to network printer. " & vbCrLf & _

             "Please contact the Helpdesk @ ext 345" & vbCrLf & _

             "and ask them to check the " & strPrtServer & " server." & _

             vbCrLf & vbCrLf & _

             "Let them know that you are unable to connect to the '" _

             & strPrtShare & "' printer"

    objWshShell.Popup strMsg,, "Logon Error !", 48

  Else

    Call UserPrompt ("Successfully added printer connection to " & _ 

    strPrtPath)

  End If



  Set objPrinter = Nothing



End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Mapping a drive to a shared folder

This routine is where the drive mapping occurs. It first removes any preexisting drive mapping that might be using the designated drive letter. Then, it verifies that the share is accessible and creates the mapping. If the share is not accessible, the user will be prompted with an error message that lets him know he should call the help desk.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      MapDrive

'

' Purpose:  Map a drive to a shared folder

'

' Input:

'           strDrive    Drive letter to which share is mapped

'           strServer   Name of server that hosts the share

'           strShare    Share name

'

' Output:

'

' Usage:

'           Call MapDrive ("X:", "StaffSvr1", "StaffShare1")

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub MapDrive( strDrive, strServer, strShare )



  On Error Resume Next



  Dim strPath       'Full path to printer share

  Dim blnError      'True / False error condition



  blnError = False



  'Disconnect Drive if drive letter is already mapped.

  'This assures everyone has the same drive mappings



  If objFileSys.DriveExists(strDrive) = True Then

    objWshNetwork.RemoveNetworkDrive strDrive, , True

  End If



  'Build path to share

  strPath = "\\" & strServer & "\" & strShare



  'Test to see if share exists. Proceed if yes, set error condition if no.

  If objFileSys.DriveExists(strPath) = True Then

    Err.Clear

    objWshNetwork.MapNetworkDrive strDrive, strPath

  Else

    blnError = True

  End If



  'Check error condition and output appropriate user message

  If Err.Number <> 0 OR blnError = True Then

    'Display message box informing user that the connection failed

    strMsg = "Unable to connect to network share. " & vbCrLf & _

             "Please contact the Helpdesk @ ext 345 and ask them " & _

             "to check the " & strServer & " server." & vbCrLf & _

             "Let them know that you are unable to connect to the " & _

             "'" & strPath & "' share"

    objWshShell.Popup strMsg,, "Logon Error !", 48

  Else

    Call UserPrompt ("Successfully added mapped drive connection to " & strPath)

  End If

End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Gathering local group memberships

This routine collects information about any local groups to which the user might belong. The names of these groups get placed into the strUserGroups variable for future reference.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      GetLocalGroupMembership

'

' Purpose:  Gather all local groups to which the current user belongs

'

' Input:

'

' Output:   Local group names are added to strUserGroups

'

' Usage:    Call GetLocalGroupMembership

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub GetLocalGroupMembership



  On Error Resume Next



  Dim colGroups   'Collection of groups on the local system

  Dim objGroup    'Object reference to individual groups

  Dim objUser     'Object reference to individual group member



  'Verify system is not Windows 9x or ME

  If objWshShell.ExpandEnvironmentStrings( "%OS%" ) = "Windows_NT" Then

    'Connect to local system

    Set colGroups = GetObject( "WinNT://" & strWorkstation )

    colGroups.Filter = Array( "group" )

    'Process each group

    For Each objGroup In colGroups

      'Process each user in group

      For Each objUser in objGroup.Members

        'Check if current user belongs to group being processed

        If LCase( objUser.Name ) = LCase( strUserID ) Then

         'Add group name to list

          strUserGroups = strUserGroups & objGroup.Name & ","

        End If

      Next

    Next

    Set colGroups = Nothing

  End If



End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Gathering global group memberships

This routine is similar to the previous one, except it collects information about any global (rather than local) groups to which the user might belong. The names of the groups also get placed into the strUserGroups variable for future reference. Since some users might still be running Windows NT domains, I use the WinNT syntax instead of LDAP to perform the query, for cross-platform interoperability. This way is a little easier anyway.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      GetGlobalGroupMembership

'

' Purpose:  Gather all global groups the current user belongs to

'

' Input:

'

' Output:   Global group names are added to strUserGroups

'

' Usage:    Call GetGlobalGroupMembership

'

' Notes:    Use WinNT connection method to be backwards

'           compatible with NT 4 domains

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub GetGlobalGroupMembership



  On Error Resume Next



  Dim objNameSpace

  Dim objUser



  Const ADS_READONLY_SERVER = 4



  Set objNameSpace = GetObject( "WinNT:" )

  'Use the OpenDSObject method with the ADS_READONLY_SERVER

  'value to grab the "closest" domain controller



  'Connect to user object in the domain

  Set objUser = objNameSpace.OpenDSObject( _

    "WinNT://" & strDomain & "/" & strUserID, "", "", ADS_READONLY_SERVER)

  'Process each group

  For Each objGroup In objUser.Groups

    'Add group name to list

    strUserGroups = strUserGroups & objGroup.Name & ","

  Next

  Set objNameSpace = Nothing



End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Determining if user belongs to a specified group

This simple routine searches the list of group names that is contained in the strUserGroups variable for the specified group and returns True if the group is found.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Function: InGroup

'

' Purpose:  Determine if user belongs to specified group

'

' Input:    Name of group to test for membership

'

' Output:   True or False

'

' Usage:    If InGroup("Domain Admins") Then <do something>

'

' Requirements:

'           strUserGroups must have been previously populated via

'           GetLocalGroupMembership and/or GetGlobalGroupMembership

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Function InGroup(strGroup)



  On Error Resume Next



  InGroup = False

  'Search strUserGroups for strGroup

  If Instr( 1, LCase( strUserGroups ), LCase( strGroup ), 1) Then InGroup = True



End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Gathering basic information about the local system

Here is another routine that gathers specific information about the local computer, such as the user domain, workstation name, product type, and the path to the location from which the script is running.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      GetSystemInfo

'

' Purpose:  Gather basic information about the local system

'

' Input:

'

' Output:   strDomain, strOSProdType, strWorkstation, strLogonPath

'

' Usage:    Call GetSystemInfo

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub GetSystemInfo



  On Error Resume Next



  'Get domain name

  If objWshShell.ExpandEnvironmentStrings( "%OS%" ) = "Windows_NT" Then

    strDomain = objWshNetwork.UserDomain

  Else

    strDomain = objWshShell.RegRead( "HKLM\System\CurrentControlSet\" & _

                "Services\MSNP32\NetWorkProvider\AuthenticatingAgent" )

  End If



  'Get Product Type from Registry (WinNT, LanmanNT, ServerNT)

  strOSProdType = objWshShell.RegRead( _

    "HKLM\System\CurrentControlSet\Control\ProductOptions\ProductType")



  'Get computer name

  If IsTerminalServerSession = True Then

    'Set strWorkstation to the real name and not the name of the server

    strWorkstation = objWshShell.ExpandEnvironmentStrings( "%CLIENTNAME%" )

  Else

    strWorkstation = objWshNetwork.ComputerName

  End If



  'Get the path to the location from where the script is running

  strLogonPath = Left( Wscript.ScriptFullName, _

    ( InstrRev( Wscript.ScriptFullName, "\") -1))



End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Determining if the script is running in a terminal server session

The following routine identifies whether the user is logging on via a Windows terminal session and returns True if this is the case. The determinant test criteria is whether the workstation has a valid %ClientName% environment variable set.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Function: IsTerminalServer

'

' Purpose:  Determine if the script is running in a terminal server session

'

' Input:

'

' Output:

'           True if running in a terminal server session

'           False if not running in a terminal server session

' Usage:

'           If IsTerminalServerSession = True Then <Do Something>

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Function IsTerminalServerSession



  On Error Resume Next



  Dim strName

  

  'Detect if this is a terminal server session

  'If it is, set some names to the terminal server client name

  strName = objWshShell.ExpandEnvironmentStrings( "%CLIENTNAME%" )

  If strName <> "%CLIENTNAME%" AND strName <> "" Then _

    IsTerminalServerSession = True



End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Setting up IE for use as a status message window

I like to use Internet Explorer as a general status message screen for users. This routine gets Internet Explorer set up and ready for this purpose.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      SetupIE

'

' Purpose:  Set up Internet Explorer for use as a status message window

'

' Input:

'

' Output:

'

' Usage:    Call SetupIE

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub SetupIE



  On Error Resume Next



  Dim strTitle    'Title of IE window

  Dim intCount    'Counter used during AppActivate



  strTitle = "Logon script status"



  'Create reference to objIntExplorer

  'This will be used for the user messages. Also set IE display attributes

  Set objIntExplorer = Wscript.CreateObject("InternetExplorer.Application")

  With objIntExplorer

    .Navigate "about:blank"

    .ToolBar   = 0

    .Menubar   = 0

    .StatusBar = 0

    .Width     = 600

    .Height    = 350

    .Left      = 100

    .Top       = 100

  End With



  'Set some formating

  With objIntExplorer.Document

    .WriteLn ("<!doctype html public>")

    .WriteLn   ("<head>")

    .WriteLn    ("<title>" & strTitle & "</title>")

    .WriteLn     ("<style type=""text/css"">")

    .WriteLn      ("body {text-align: left; font-family: arial; _

                  font-size: 10pt}")

    .WriteLn     ("</style>")

    .WriteLn   ("</head>")

  End With



  'Wait for IE to finish

  Do While (objIntExplorer.Busy)

    Wscript.Sleep 200

  Loop



  'Show IE

  objIntExplorer.Visible = 1



  'Make IE the active window

  For intCount = 1 To 100

    If objWshShell.AppActivate(strTitle) Then Exit For

    WScript.Sleep 50

  Next



End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Using IE as a status message window

Finally, the last routine is just a little helper for the status message window. There's nothing fancy going on here.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      UserPrompt

'

' Purpose:  Use Internet Explorer as a status message window

'

' Input:    strPrompt

'

' Output:   Output is sent to the open Internet Explorer window

'

' Usage:

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Sub UserPrompt( strPrompt )



  On Error Resume Next



  objIntExplorer.Document.WriteLn (strPrompt & "<br />")



End Sub



''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'

' Sub:      Cleanup

'

' Purpose:  Release common objects and exit script

'

' Input:

'

' Output:

'

' Usage:    Call Cleanup

'

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Sub Cleanup



  On Error Resume Next



  Set objFileSys     = Nothing

  Set objWshNetwork  = Nothing

  Set objWshShell    = Nothing

  Set objIntExplorer = Nothing



  'Exit script

  Wscript.Quit( )



End Sub

Running the Hack

Since I still have a few NT clients on my network, I place a batch file named logon.bat in the NETLOGON shares on my domain controllers. All users are then assigned this logon.bat file as their startup script. This logon.bat file verifies that the user is on a supported platform (NT, 2000, or XP) and then kicks in the logon.vbs script via a call like this (depending on the path to the script):

cscript //nologo %0\..\logon.vbs

To keep the user informed of the logon progress, status messages are posted to an Internet Explorer window.

These are the three results of running the logon script:

  • The user gets the appropriate printer added.

  • The user gets mapped drives added where appropriate.

  • The user's homepage is reset (depending on group membership and computer name).

This sample logon script can prove useful for small organizations. However, storing all the mapping information in the script can soon become unwieldy. If you are in a large organization and want to perform tasks at logon based on computer names, it might be best to offload the mapping information to a network database that can be queried via the logon script.

?Dan Thomson