Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I retrieve information about the printer driver used by a specific printer?

-- RW

SpacerHey, Scripting Guy! AnswerScript Center

Hey, RW. Did you say something? Oh, right: printer drivers. You’ll have to excuse us today: the Scripting Guys (well, one of them anyway) are in mourning. That’s because the Colt League All-Star team he helped coached finished third in the Northwest Regional Tournament. What’s wrong with finishing third in the Northwest region? Well, nothing…except that the team that finished first gets to go to California and play in the Zone tournament, with the winner there going on to the Colt League World series. Everyone else - including the team that finished third - gets to go home.

Anyway, thanks for asking: given time, we’ll recover and get back to our usual rollicking selves. Try us again in a month or two. Or maybe next year sometime. Perhaps by 2008 we’ll be ready to answer questions again. Until then….

Um, never mind: our manager just informed us that we’ve made a remarkable recovery and are ready to answer questions now. (Obviously he doesn’t understand how important Colt League baseball is.) So we’ll answer your question. And then we’ll go back into mourning.

Because this is a printing-related question we have the usual caveat: we can show you a solution that works great on Windows XP and Windows Server 2003, but won’t work on Windows 2000 or any other version of Windows. On those other platforms you can use a script like this one to return the name of the print driver used by a specific printer, but that’s pretty much all the information you can get:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
    ("Select * From Win32_Printer Where DeviceID='\\\\atl-ps-1\\printer1' ")

For Each objItem in colItems
    Wscript.Echo objItem.Name
    Wscript.Echo objItem.DriverName
Next

Better than nothing, we suppose, but the name alone doesn’t exactly qualify as “details” about the printer driver. If you want detailed information like that, you need to use a script like this one, a script that runs only on Windows XP or Windows Server 2003:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
    ("Associators Of {Win32_Printer.DeviceID='\\atl-ps-01\printer1'} " _
        & "WHERE AssocClass = Win32_DriverForDevice Role=Antecedent")

For Each objItem in colItems
    Wscript.Echo objItem.Name
    Wscript.Echo objItem.DriverPath
Next

What we’re doing here is taking advantage of two new classes that were added to Windows XP and Windows Server 2003. Although you don’t see it explicitly mentioned in the script, we’re using the new Win32_PrinterDriver class to retrieve information about the printer driver; the properties Name and DriverPath (both echoed in our For Each loop) are properties of the Win32_PrinterDriver class.

The second class - which is explicitly spelled-out in the script - is the Win32_DriverForDevice class. This is an association class which, as the name implies, makes an association between two classes; in this case, Win32_DriverForDevice makes an association between a printer in the Win32_Printer class and a printer driver in the Win32_PrinterDriver class. To make this association we need to use an Associators Of query like this one:

Set colItems = objWMIService.ExecQuery _
    ("Associators Of {Win32_Printer.DeviceID='\\atl-ps-01\printer1'} " _
        & "WHERE AssocClass = Win32_DriverForDevice Role=Antecedent")

In plain English (not exactly a Scripting Guys specialty!) this query says, “For all the printers with the DeviceID \\atl-ps-01\printer1 use the Win32_DriverForDevice class to retrieve all the printer drivers associated with that printer.”

As usual, the query returns a collection, in this case a collection of all the printer drivers associated with the printer \\atl-ps-01\printer1. In our For Each loop we iterate through the collection and echo back the Name and DriverPath properties. Problem solved.

That much you could probably figure out for yourself; the query’s a bit odd-looking, but fairly intuitive. Except maybe for one thing: what does Role=Antecedent mean? Well, in the wonderful world of WMI an antecedent object is the independent object in a relationship; in other words, you can have all kinds of print drivers, none of which are dependent on a particular printer. However, a printer can have only one print driver, which means the printer plays a Dependent role in the relationship. (Yes, it does sound like an episode of Desperate Housewives, doesn’t it?) That means with a few tweaks we can flip this script inside-out and have it query the Win32_PrinterDriver class to return the names of all the printers that use a specified driver:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
    ("Associators Of {Win32_PrinterDriver.Name='Xerox Document Centre 255 PS,3,Windows NT x86'} " _
        & "WHERE AssocClass = Win32_DriverForDevice Role=Dependent")

For Each objItem in colItems
    Wscript.Echo objItem.DeviceID
Next

Give it a try and see what happens.

Now, if you’ll excuse us, we have…work…to do….

(In case you’re wondering, there’s a reason why there aren’t any books titled The Third-Best and the Third-Brightest: third-place isn’t anywhere near as much fun as it might sound!)