views:

639

answers:

4

I have the following automation code:

lPrintSetup := fWordObject.Application.Dialogs.Item(wdDialogFilePrintSetup);
lPrintSetup.Printer := 'MyPrinter';
lPrintSetup.DoNotSetAsSysDefault := True;
lPrintSetup.Execute;
lPrintSetup := Null;

The Printer property is giving me some problems, sometimes Execute crashes with an EOleException (0x800A1460 (error code 5216): There is a printer error) because of a wrong printername.

I have printer information of all printers in a _PRINTER_INFO_2 record which I obtained by a EnumPrinters API-call. How can I compose the right printername for Word given the information in a _PRINTER_INFO_2 record? It has work with at least Windows 2000, Word 2000 and Citrix.

Some background info:

Our application first filled the Printername with a self constructed printername. This gave problems with Citrix clients, so for Citrix clients we took the _PRINTER_INFO_2.pPortName and deleted the Client:#: part. This is working for the majority of our customers, but sometimes still the printer error shows up.

What I have tried so far (on Windows XP SP3, Word 2007):

  • Just take the _PRINTER_INFO_2.pPrinterName. Problem is that when you modify printernames on purpose (renaming 'PDFCreator' to 'HP DESKJET 520 on MYPC') it crashes on the latter (while selecting this printer in Word works).
  • Composing a printername like this: lPrintSetup.Printer := PRINTER_INFO_2.pPrinterName + ' on ' + PRINTER_INFO_2.pPortname. Seems to work always! But googling around showed that ' on ' is localized, so I'm not sure if that's going to work on non-english Windows versions. Edit: does not work always :(

Another solution I found on the web:

When reading the printername from Word it has the form of "Printername on Ne01:", where Ne01 is ranged from Ne00: to Ne99:. The solution suggested taking the printername and just try to set it while looping from Ne00: to Ne99:. When .Execute doesn't crash, you've got the right one. I'm not very fond of this 'trail and error' method.

A: 

I'm not sure if you've tried this, or if its of any use, but you can get a list of all the printers on the system from the Printer.Printers object make sure you add Printers to the Uses clause of your unit.

This should then list the actual names on the system and you may be able to use this information to do what you want.

Toby Allen
A: 

As stated you can get a list of printer names using the Printer.Printers which is a TStringList with the name of the printer on each item.

This code gives the default printer name

Printer.Printers[Printer.PrinterIndex]
Aldo
A: 

Some minutes ago I learned, that word2k not only wants Printernames like "Printername on Ne01:" it only wants the port (NEnn) uppercase "Printername on NE01:"

Volkmar
I tested on Word 2000, it accepted "Ne00:" too.
The_Fox
A: 

I figured it out. Word has the printername in the form of "Printername on NE01:". Ne01: is the printerport as specified in the devices section of win.ini. So now I compose the printername as _PRINTER_INFO_2.pPrinterName + ' on ' + <PrinterPort from win.ini> and set that name for the printer property of the FilePrintSetup dialog.

This is much better than to resort to the trail-and-error method mentioned in my question.

The_Fox
Didn't you say that you don't want to do this because of the localized "on"?
DR
I tested this on a Dutch Windows Vista Business edition and "on" wasn't localized, so I took my chances. I did wrap the new code in a try except, when it fails, I fall back to our old method of assigning a printer.
The_Fox