January 13th, 2005

How Can I Map a Printer, But Only If the User Doesn’t Have a Local Printer?

Hey, Scripting Guy! Question

Hey, Scripting Guy! I’d like to have a logon script that maps a network printer for each user unless that user already has a local printer. If they have a local printer, I don’t want to add the network printer. Is that possible?

— AG

SpacerHey, Scripting Guy! AnswerScript Center

Hey, AG. Not only is that possible, but it’s actually pretty easy, especially if you’re running Windows XP or Windows 2003. We’ve got two issues here: we need some code that maps a network printer, and we need some code that figures out whether or not the user has a local printer. Let’s start with the code for mapping a network printer:

Set objNetwork = CreateObject(“WScript.Network”)
objNetwork.AddWindowsPrinterConnection “\\PrintServer1\Xerox300”
objNetwork.SetDefaultPrinter “\\PrintServer1\Xerox300”

If you’re sitting there waiting patiently for the rest of the code, well, it’s going to be a long wait: that’s all the code you need to map a network printer. In the first line, we create an instance of the WSH Network object. In the second line, we use the AddWindowsPrinterConnection method to make a connection to the printer Xerox300 (found on the print server named PrintServer1). That’s really all we need. Line 3, which makes the new printer the default printer, is optional. We added it just to show you how easy it is to make a printer the default printer.

Now, what about determining whether or not there are any local printers connected to a computer? As it turns out, in Windows XP and Windows 2003 the WMI class Win32_Printer has a property named Local. If this property is TRUE, then the printer in question is a local printer; if this property is FALSE, then the printer in question is a network printer. If we want to know if there are any local printers attached to a computer, all we have to do is query for all the printers where the Local property is TRUE:

strComputer = “.”

Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”) Set colPrinters = objWMIService.ExecQuery _ (“Select * From Win32_Printer Where Local = TRUE”)

We can then check the Count property to see how many local printers were found. If the Count equals 0, then no local printers were found. In that case, we’d go ahead and map a network printer. If the Count is greater than 0, at least one local printer was found. In that case, we don’t want to map a network printer, so we just don’t do anything at all (something we Scripting Guys are incredibly good at).

Here’s a complete script that – on Windows XP and Windows 2003 – maps a network printer if no local printers are found:

strComputer = “.”

Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”) Set colPrinters = objWMIService.ExecQuery _ (“Select * From Win32_Printer Where Local = TRUE”)

If colPrinters.Count = 0 Then Set objNetwork = CreateObject(“WScript.Network”) objNetwork.AddWindowsPrinterConnection “\\PrintServer1\Xerox300” objNetwork.SetDefaultPrinter “\\PrintServer1\Xerox300” End If

The more observant (or paranoid) among you might have noticed that we keep talking about Windows XP and Windows 2003, but we’ve been strangely silent when it comes to other versions of Windows. Does that mean you can’t perform this task on, say, Windows 2000? No, it just means that – prior to Windows XP – the Win32_Printer class did not include a Local property. Consequently, we can’t query for all printers where Local = TRUE.

But that’s OK; as usual, we can find a way around this limitation. Previous versions of the Win32_Printer do include a property named Attributes. One of the “switches” housed within the Attributes property tells you whether or not the printer is a local printer. If this particular bit (equal to 64) is enabled, then the printer is local; if it is not enabled, then the printer is a network printer.

Therefore, we can use some Boolean logic to test whether or not a computer has any local printers. We don’t have time to explain Boolean logic today; for that you might want to check out this section of the Microsoft Windows 2000 Scripting Guide. In the meantime, here’s a script that will work on Windows 2000:

blnLocal = FALSE
strComputer = “.”

Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”) Set colPrinters = objWMIService.ExecQuery(“Select * From Win32_Printer”)

For Each objPrinter in colPrinters If objPrinter.Attributes And 64 Then blnLocal = TRUE End If Next

If blnLocal = FALSE Set objNetwork = CreateObject(“WScript.Network”) objNetwork.AddWindowsPrinterConnection “\\PrintServer1\Xerox300” objNetwork.SetDefaultPrinter “\\PrintServer1\Xerox300” End If

In this script, we set a variable named blnLocal to FALSE. We then retrieve a list of all the printers on a computer and check each one to see if the local printer bit has been set. That’s what this line of code does:

If objPrinter.Attributes And 64 Then

If a local printer is found, we set the value of blnLocal to TRUE. At the end of the script, if blnLocal is TRUE, we know that a local printer was found and the script simply ends. If blnLocal is FALSE, however, that means that no local printer was found. Therefore, we go ahead and map the network printer.

Whew! But it works.

Author

0 comments

Discussion are closed.