A long while back I posted an entry regarding how to install a printer driver programmatically by shelling out and using rundll32.exe to execute the PrintUi.dll which can handle a variety of print tasks including installing a printer driver. This code's been working fine, but it's been giving me some problems under Vista for a couple of reasons.

The firsts issue is that I use the driver to install a PostScript driver so I can print a PostScript file to disk which later can be converted by GhostScript. To do this I've been using one of the default installed printer drivers for Windows which has been:

Apple Color LW 12/660 PS

Unfortunately this driver no longer exists in the default printer list in Vista. In fact, Microsoft ditched all the Apple printers - well they are a bit uhm dated. <s> So the next step was to find a driver that exists under WinXp, Win2003 and Vista (don't have older versions around to check but it might work under Win2k as well). The driver I ended up picking was:

Xerox Phaser 1235 PS

But even after switching to the new and available printer I continued to get error message from the driver installation routine. The main reason is that I previously had used the /v[ersion] switch with "Windows 2000 and XP" which works fine for all OS's through XP. On Vista however, only "Windows XP" works explicitly (there's no Windows Vista switch as far as I can tell).

In the end the following two command lines will install the printer driver:

C:\Windows\system32\rundll32.exe printui.dll,PrintUIEntry /ia /m "Xerox Phaser 1235 PS" /h "Intel" /v "Windows XP" /f "C:\Windows\inf\ntprint.inf" /u
C:\Windows\system32\rundll32.exe printui.dll,PrintUIEntry /if /b "Xerox Phaser 1235 PS" /f "C:\Windows\inf\ntprint.inf" /r "lpt1:" /m "Xerox Phaser 1235 PS"

I'm using this code as part of a setup routine that runs inside of West Wind Web Connection (a FoxPro application) application and here's the complete logic to do the driver installation:

************************************************************************

* InstallPrinterDriver

*********************************************

***  Function: Installs a Windows Printer driver from the stock

***            Windows driver library

***    Assume:

***      Pass:

***    Return:

************************************************************************

FUNCTION InstallPrinterDriver(lcDriverName,lcPrinterName)

LOCAL lcOs, llResult

 

IF EMPTY(lcDriverName)

 *** This color PS driver exists under Win2003, Vista and XP

 lcDriverName = "Xerox Phaser 1235 PS"

 * lcDriverName = "Apple Color LW 12/660 PS"

ENDIF

IF EMPTY(lcPrinterName)

  lcPrinterName = lcDriverName

ENDIF 

LOCAL ARRAY laPrinters[1]

 

lnCount = APRINTERS(laPrinters)

FOR lnX = 1 TO lnCount

   IF LOWER(lcPrinterName) == LOWER(laPrinters[lnX,1])

      RETURN .t.

   ENDIF

ENDFOR  

 

lcOS = "Windows 2000 or XP"

IF OS(3) = "6"  && Vista requires XP setting

   lcOS = "Windows XP"

ENDIF

 

loAPI = CREATEOBJECT("wwAPI")

lcExe = loAPI.GetSystemDir() + "rundll32.exe"

lcCmdLine = [printui.dll,PrintUIEntry /ia /m "] + lcDriverName + [" /h "Intel" /v "] + lcOS + [" /f "] + loAPI.GetSystemDir(.t.)+ [inf\ntprint.inf" /u"]

 

llResult = CreateProcess(lcExe,lcCmdLine,2,.t.)

IF !llResult

   RETURN .F.

ENDIF  

 

lcCmdLine = [printui.dll,PrintUIEntry /if /b "] + lcPrinterName + [" /f "] + loAPI.GetSystemDir(.T.) + [inf\ntprint.inf" /r "lpt1:" /m "] + lcDriverName + ["]

 

llResult = CreateProcess(lcExe,lcCmdLine,2,.t.)

IF !llResult

   RETURN .F.

ENDIF  

 

RETURN .T.

 

This code should adapt reasonably well to anything that can shell out…

 

The documentation for printui.dll can be found here:

http://www.microsoft.com/windowsserver2003/techinfo/overview/printuidll.mspx

 

It's not exactly exhaustive - there's no explanation of any of the switches or which combinations are valid - but if you need to set additional flags it's good place to start experimenting.