My company has offices in several locations. Our computers and users are placed in Active Directory (AD) organizational units (OUs) that are structured after those locations. However, until recently, our network printers had been scattered to the four winds and controlled by miscellaneous workstations around the office. Thus, if a workstation failed or went offline, access to that network printer went with it.

I knew that situation had to change, so I began to plan for the deployment of a printer server. However, I wanted to deploy the printer connections without having to visit every workstation. I needed an elegant printer deployment script for our workstations.

In the past, I had used a .vbs script to assign printers to computers, but it used a simple command such as

objNetwork.AddWindowsPrinterConnection _

This command added a nonqualified printer for all the users in the company, no matter what OU they were in. I wanted the new .vbs script to work differently. I had three specific goals in mind:

  • Goal 1: The script should assign available printer connections to a computer based on the computer's OU and not on who logs on to that computer.
  • Goal 2: The script should remove irrelevant or old network printer connections without removing the local printer connections.
  • Goal 3: The script should assign each user a default printer connection.

By meeting these three goals, I would be able to create a .vbs script that I could run as a Group Policy-based logon script. That way, assigning a printer to a computer would be as simple as adding a computer to a domain and putting that computer in the appropriate OU.

Accomplishing Goal 1
To assign available printer connections based on a computer's OU, I first had to determine that OU. The ADSystemInfo object in Active Directory Service Interfaces (ADSI) is the key to learning the OU to which the local computer belongs. The ADSystemInfo object's ComputerName property returns the local computer's distinguished name (DN), which includes the OU.

With the OU in hand, I could assign printer connections by using VBScript's InStr function within an If…Then…Else statement. For example, in the code snippet that Listing 1 shows, the InStr function searches for the local computer's DN (which strComputerOU contains) for the string "OU=Target OU" (in a real script, Target would be the name of an actual OU). The InStr function returns a numerical value that specifies the string's location. When the function doesn't find the string, it returns a 0. So, if the returned value is greater than 0 (i.e., the "OU=Target OU" string is present), the three printer connections are added.

Accomplishing Goal 2
On the users' workstations, there were many unwanted network printer connections that had to be removed. At first, I considered doing some sort of registry hack, but I was leery of modifying the registry. I then found that I could enumerate through all the printer connections on a computer by using the EnumPrinterConnections method of the WshNetwork object in Windows Script Host (WSH). However, this method returns all printer connections, including the local printer connections. Because I wanted to remove only the network printer connections, I had to do some filtering to find any double backslashes (\\) at the beginning of a printer resource. As the code snippet in Listing 2 shows, a counter can be used to enumerate through the printer connections returned by the EnumPrinterConnections method. The Mid function checks to see whether the first and second character of each printer connection is a backslash. If so, the WshNetwork object's RemovePrinterConnection method removes that network printer connection.

Accomplishing Goal 3
The next task was to figure out how to assign each user a default network printer connection. Although each office has a default printer that everyone should print to, many users request a different default printer. (The default printer is the printer that a print job immediately goes to when you click the print icon.)

I determined that the easiest way to assign default printer connections was to create default-printer groups and add users to those groups. For example, you can create a "Default Printer 1 Users" group for those users who want to print by default to an HP LaserJet 4100 printer, a "Default Printer 2 Users" group for those users who wanted to print by default to a Xerox Phaser 6120 printer, and so on.

After adding users to the appropriate groups, I wrote the code that assigns the default printer connection based on the user's default-printer group. Listing 3 shows code snippet that accomplishes this task. In this code, the WshNetwork object's UserName property returns the name of the currently logged-on user. The username and the domain name (which you need to hardcode in) are assembled into an ADsPath, which is used to get the ADSI User object representing the user. The User object's Groups method returns a collection of the groups to which the user belongs. A For Each...Next statement iterates through each group in the collection. Each group's name is compared with names of the three default-printer groups. When a match occurs, the WshNetwork object's SetDefaultPrinter method assigns the appropriate default printer connection.

Putting It All Together
Finally, all that was left to do was to work the code snippets into a cohesive script—AssignPrinters.vbs, which Listing 4 shows—and run it as a Group Policy-based logon script. Now when a user logs on, the script removes old network printer mappings, assigns available printer connections based on the OU to which the computer belongs, and assigns the default printer connection based on the default-printer group to which the user belongs. And when new employees start, I simply create the user accounts and add them to the appropriate default-printer group. Then when the new employees log on, they have all the printer resources they need.

—Woody Holbert

Share Your Scripting Experiences
