Hey, Scripting Guy! Is it possible to delete or remove all network printers from a workstation with a VBScript script, similar to the way you removed all the network drives on a computer?
— WDC
Hey, WDC. If you’ve been following our daily TechEd preview report, then you know that the Scripting Guys have been busy preparing for their upcoming trip to Barcelona and TechEd IT Forum. The preview report gives you an inside look at what the Scripting Guys are doing to get ready for the trip; before we answer today’s question, however, we thought we’d give you an exclusive super-duper inside look at what we’re doing to get ready for the trip.
For example, here’s the transcript of the Scripting Guys’ planning session that took place earlier today:
Jean Ross: We have way too much to do.
The Scripting Guy Who Writes This Column: That’s true, we do have way too much to do.
Jean Ross: I don’t see how we can possibly get everything done in time.
The Scripting Guy Who Writes This Column: Me either, I – wait, I know: suppose that in addition to everything else we’re doing, we added three more things to the pile? That would solve all our problems, right?
Jean Ross: —
Well, uh, never mind what Scripting Guy Jean Ross said. Poor thing; she’s been under a lot of stress lately.
Although, admittedly, most of that stress does come from having to work with Scripting Guy who writes this column.
In other words, things are going just great. Assuming that Jean doesn’t explode between now and November 8th, the Scripting Guys will hop onto a plane that morning and head for Spain.
Note. You know, you’d be surprised how many people have said that very same thing: poor Spain. Wonder what you all mean by that? |
At any rate, things are going so well that we have plenty of time to sit down and chat about a script that can remove all the network printers from a workstation. In the interests of fair disclosure we should note that, back in December of 2005 (when Scripting Guy Greg Stemp was just a sophomore in high school), we showed everyone a similar script, one that could remove all the local printers from a computer. Depending on how you want to look at, that means that we’re cheating a little here; after all, we only have to make one minor change to that script and it will remove all the network printers instead.
You know, now that we think about it, that doesn’t sound like cheating a little, that sounds like cheating a lot.
On the other hand, we also noted in that December 2005 column that the script in question would not work on Windows 2000; instead, it would only run on versions of Windows that came after Windows 2000. We also said, “We’ll see what we can do about addressing this issue on Windows 2000 computers. We won’t make any promises, but we’ll look into it.” And now, less than 2 years later, we’ve actually gone ahead and looked into it. Based on that exhaustive research, we’ll show you how to delete network printers on post-Windows 2000 computers first, and then show you how to perform this very same task on a Windows 2000 machine.
And then at that point we’ll have done everything we ever promised to do.
More or less ….
Here’s the post-Windows 2000 script:
strComputer = “.”Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
Set colInstalledPrinters = objWMIService.ExecQuery _ (“Select * From Win32_Printer Where Network = True”)
For Each objPrinter in colInstalledPrinters objPrinter.Delete_ Next
As you can see, there’s really not much to this script. We start out by connecting to the WMI service on the local computer. As is invariably the case, however, we could also use this script to remove printers from a remote machine. How? Simply by assigning the name of that remote computer to the variable strComputer, like so:
strComputer = “atl-ws-001”
After we connect to the WMI service we then issue the following query in order to return a collection of all the network printers installed on the computer:
Set colInstalledPrinters = objWMIService.ExecQuery _ (“Select * From Win32_Printer Where Network = True”)
The secret here – not that it’s much of a secret, mind you – is that we included a Where clause that limits the returned data to printers where the Network property is True; needless to say, that property will be True only if we’re dealing with a network printer. This, by the way, is one reason the script won’t work on a Windows 2000 machine: the Win32_Printer class in Windows 2000 doesn’t include the Network property. (That property was introduced in Windows XP). And no, there is zero chance that the Windows 2000 version of the Win32_Printer class will be updated to include this property.
But don’t worry, Windows 2000 users: like we said, we’ll show you a way to work around that issue. Just be patient. (Actually, you don’t even need to be all that patient; after all, we’re just about done with the post-Windows 2000 version.)
Once we get back our collection of network printers we set up a For Each loop to loop through each of the items in that collection. For each item all we have to do is call the Delete_ method and that printer connection will be removed:
objPrinter.Delete_
Tah-dah!
Now, what about the Windows 2000 version? Well, this is bit trickier, and for two reasons. First, and as we noted earlier, the Network property doesn’t exist in Windows 2000; that makes it harder to identify which printers are network printers and which ones aren’t. Second, it’s not just the Network property that the Win32_Printer class doesn’t support; Win32_Printer doesn’t support the Delete_ method, either. That means we have to do a bit of a workaround just to get the collection of network printers in the first place, and then we have to hand that collection off to Windows Script Host (WSH) and let it do the deleting for us.
Note. This also means that the Windows 2000 version of the script can only be run on the local computer. That’s because the WSH methods for adding/removing printer connections can’t be used against remote machines. |
For better or worse, here’s the Windows 2000 script:
Const NETWORK = 22Set objNetwork = CreateObject(“WScript.Network”)
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 NETWORK Then strPrinter = objPrinter.Name objNetwork.RemovePrinterConnection strPrinter End If Next
This time around we start out by defining a constant NETWORK and setting the value to 22; we’ll use this constant to help us determine whether a given printer is a network printer or a local printer. After that we create an instance of the Wscript.Network object, the WSH object we can use to remove printers from a computer.
From there we bind to the WMI service (remember, local computer only) and then use the following line of code to return a collection of all the printers on a computer:
Set colPrinters = objWMIService.ExecQuery(“Select * From Win32_Printer”)
Now, you’re right: we don’t want to remove all the printers on a computer, do we? Instead, we want to remove only network printers. That’s why, after setting up a For Each loop to walk through the collection of printers, we run this line of code:
If objPrinter.Attributes And NETWORK Then
As it turns out, the Attributes property is a “bitmask” property, a property that can contain more than one value. (For more information about bitmask properties see this Scripting Guys webcast.) Bitmasks are composed of “switches” that can be either on or off; for example, the Attributes property has a “switch” with a value of 22 that tells us whether a printer is a network printer. If this switch is on then we have a network printer; if this switch is off then we have a local printer. The preceding line of code simply checks to see if the Network switch is on. If it is, we assign the printer Name to a variable named strPrinter, then use this line of code to delete that printer connection:
objNetwork.RemovePrinterConnection strPrinter
From there we loop around and repeat the process with the next printer in the connection. It’s not the most elegant script in the world, and it is restricted to the local machine (making it a candidate for inclusion in a logon script) but it works.
By the way, local printers have their own switch, one with a value of 100. How does that help you search for local printers? Well, to search for local printers you can first define a constant named LOCAL, with a value of 100:
Const LOCAL = 100
And then you can check each printer on the computer to see if the local switch is on or off:
If objPrinter.Attributes And LOCAL Then
In the meantime, it’s back to work for the Scripting Guy who writes this column. As you might expect, we’re looking forward to talking to as many people as we can in Barcelona; if you’re attending TechEd IT Forum take a minute or two to swing by booth 22 in the Ask the Experts section. Sure, you’ll have to spend a minute chatting with a Scripting Guy, but maybe you’ll get lucky: maybe you’ll get to talk to Jean instead of the Scripting Guy who writes this column. Either way, you’ll also get a copy of Dr. Scripto’s Fun Book, you’ll get a bonus CD with hundreds of scripting-related columns and articles (plus a scripting song or two), and you’ll have a chance to win one of the few remaining Dr. Scripto bobblehead dolls. What more could you ask?
Actually, that’s a really good idea and someone should ask her about that. But not us; as it is, the Scripting Guy who writes this column has decided it might be best to wait a day or two before approaching with any new ideas or projects.
0 comments