Setting correct printer in MS Word through automat

2019-08-19 09:01发布

问题:

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.

回答1:

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.



回答2:

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]


回答3:

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:"



回答4:

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.