Making the right printer available to the right people in larger networks or in a company in which people move around from system to system can be complicated. Using the same printer all the time doesn't make sense for telecommuters or sales people who use laptops and regularly plug in at different locations. And when several people share a computer or one person uses more than one workstation, you need some way to provide the right printer for the given conditions. A VBScript program can automatically install and connect to printers at user logon according to user or computer identity, then unmap the printer connection when the user logs off. This scenario works best on Windows NTbased OSs such as Windows XP, Windows 2000, and NT because you can create the printer connection and install the drivers in one step. However, you can also use the technique on Windows 9x computers if you've preinstalled drivers.
As I explain in "Connecting Users to Network Resources," June 2002, InstantDoc ID 24893, Windows Script Host (WSH) abstracts the interface of many Win32 objects, including WshNetwork (aka WScript.Network), a collection of network resources, shared drives, and printers. The computer name (ComputerName), username (UserName), and computer domain (UserDomain) are all properties of the WshNetwork object. WshNetwork supports several methods for network access to drives and printers. To map a printer explicitly to a port, you use the AddPrinterConnection method. To create a Windows printer connection (and automatically install the driver on XP, Win2K, or NT), use the AddWindowsPrinterConnection method, which I'll use in the examples in this article. To set the default printer for a computer, use the SetDefaultPrinter method. You can use WshNetwork to install support for shared network printers, and you can use the Select Case statement and InputBox function to build flexibility into the process.
Creating a Generic Printer Connection
Listing 1 shows the simplest way to use VBScript to install a printer. The code in this example
- defines the variables that the script will use (at callout A) so that if you mistype a variable name later in the code, you'll receive an error message instead of creating a new variable.
- creates a connection to the WshNetwork object (at callout B). You must create this connection before you can call on the object's properties and methods.
- assigns the printer's Universal Naming Convention (UNC) path to the sPrintPath variable (at callout C) so that the path is easier to refer to.
- calls the appropriate method to create the printer connection and make it the default, supplying—as an argument to the method—the variable that represents the printer path (at callout D).
When I assign a valid path in the code at callout C in Listing 1, the script connects to the specified printer if the server is an NT-based computer. To use this script in your environment, simply replace the path in callout C with your valid UNC printer path.
You can use the same script to install support for more than one printer and make one printer the default. To do so, define a separate variable for each printer, assign a separate printer path and call the AddWindowsPrinterConnection method for each variable, and call the SetDefaultPrinter method to set one of the variables as the default printer. (Default printer settings work just as the default printer settings available from the GUI do: If you make more than one printer the default, the script will accept as the default the last printer you specified.)
Creating a Computer- or User-Specific Printer Connection
The script above is a good start, but it isn't all that powerful—you haven't yet done anything that you can't accomplish with the Net Print command or the Con2prt tool in the Microsoft Windows 2000 Resource Kit. To install printers according to computer or user identity, you need to make the script retrieve the identity and perform actions based on the retrieved data. Listing 2 shows a script that installs printers according to computer identity, so long as the computer you're running the script on has a connection to the print server.
This script first defines the variables and establishes a connection to the WshNetwork object. However, the code that the script introduces in Listing 2 exploits the Select Case statement, which makes this script much more powerful. (For a detailed discussion of the Select Case statement, see "Connecting Users to Network Resources.") Including the Select Case statement permits the script to read the local computer name and make a decision about which printer to install based on that information. The value of the computer name determines the value for sPrintPath, which is then plugged into the AddWindowsPrinterConnection and SetDefaultPrinter methods.
Thus, the code at callout A in Listing 2 uses the Select Case statement to test for the computer name—the value of the oNetwork.ComputerName property. If the value is "Gamma", the script assigns the "\\server\printer1" path to the variable sPrintPath; if the value of the property is "Geektoy", the script assigns the "\\server\printer2"path to sPrintPath. So that I don't need to list every computer in the network, I included a Case Else option that represents the path of a typical printer connection—"\\server\printer3"—for all systems other than "Gamma" or "Geektoy". (If you skip the Case Else line and the ComputerName value passed to the script doesn't match the value in any of the Case option lines, the script simply skips to the first line after End Select.) Again, to use the script that Listing 2 shows, replace the printer paths and computer names with paths and names in your environment.
To connect to printers according to user identity, you can write a similar script that uses the name of the logged-on user (i.e., the value of oNetwork.UserName) as the Select Case argument. Web Listing 1 (http://www.winnetmag.com, InstantDoc ID 25652) shows the Select Case statement for such a script. The rest of the script would look like the Listing 2 script.
User-specific mappings aren't persistent. For example, suppose that Lisa logs on and that the Web Listing 1 statement maps her printer; Lisa then logs off. After Bruce logs on to the same computer and the statement maps his printer, he'll see only his printer—not his and Lisa's printers. When you want to disable a computer-specific mapping or a mapping that won't be replaced by another mapping, however, you need to manually remove the printer or call the WshNetwork object's RemovePrinterConnection method, supplying the printer path as an argument. You can include such a call in the logoff script for Win2K computers.
Creating a Location-Specific Printer Connection
The Listing 2 script connects one computer to a default printer, depending on the computer name. But what if you need to connect multiple computers in a location to the printer that's physically close to that location—and repeat this process for several locations? You could add to the Listing 2 script a Select Case statement with a Case option for each computer, or you could create a different version of the script for the computers in each location. In a large network, either option can become cumbersome. A third way exists, though: You can write a script that asks users to tell you where they are (e.g., library, second floor), then connects the user's system to the closest printer. (This type of script requires user input, but as long as you trust your user base to know what part of the building they're in and prompt them for the type of input you want, it should work. You can configure the script either to end or restart if users enter a location that doesn't exist.)
The script in Listing 3 creates an input box that prompts users to specify their location. The VBScript input box always displays an OK button and a Cancel button, but you must specify the user prompt and you can specify two additional optional arguments—title and default—to customize the input box's appearance. The title appears in the input box's title bar, and the default is a text string that appears in the input box's text box when the script first displays the input box to the user. The code at callout A in Listing 3 sets the prompt for the input box. The code doesn't set a title or default text, but if you want to do so, you must place the prompt, title, and default arguments in the following order:
InputBox(prompt, title, default)
The prompt and title variables are strings. Therefore, make sure to enclose the strings in quotation marks (").
The script then uses a Select Case statement to evaluate the user input and determine which printer to connect to. If the user typed an invalid choice, the script jumps to the Case Else option, which uses the MsgBox function to display a message box with text you specify and uses the WScript.Quit method to end the script. In other words, the script doesn't connect to a printer if the input provided doesn't match a valid location. Alternatively, the script could assign a generic printer or (to make the example a bit more complicated) prompt the user for a location again (in case the user mistyped the location the first time). Regardless, you must provide some way to end the script or to assign some value to sPrinterPath before the script calls the AddWindowsPrinterConnection method, or an error will occur when the script tries to connect to the printer without a path to use as an argument.
You can use Win2K Group Policy to set default printers or disable the Control Panel Add Printers applet. Also, you can hide shared printers (by ending their names in a dollar sign—$) so that users can connect only to the printers programmatically assigned to their username, computer name, or location. This setup will prevent users in Lab A from mistakenly sending their print jobs to Lab Z, three buildings away.
WshNetwork properties and methods aren't the only way to manage printers through VBScript—you could use the PrintAdmin tool in the Win2K resource kit or Windows Management Instrumentation (WMI) and the Active Directory Service Interfaces (ADSI)—but they're the simplest. Don't worry, we'll get to WMI and ADSI in good time.