Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using ShellExecute to print a PDF to specific printer 2

Status
Not open for further replies.

KarenLloyd

Programmer
Nov 23, 2005
141
GB
Hi Gurus

With reference to so many threads (thread184-698845, thread184-1485500 and thread184-1485500 to name but a few...) I needed to print a PDF from VFP6 and I thank you for your tips for ShellExecute, which I am finding increasingly useful for different things - file case naming etc.

I have had to pull together a few different elements so that I can print a VFP6 report (a) to the desired printer, (b) to a PDF and then (c) using PDFTK to watermark the PDF. (I know that I should look to VFP9 for these features such as watermarking... but I also need to figure out the installation side of VFP9 - such as is it a DLL distribution or an each machine registry issue...) Anyway - both the invoice report FRX and the filecopy/watermarked PDF need to go to a printer that is not the default printer.

Bearing in mind that I am still in VFP6 - please can you give me examples of how to manage this, even if I have to add in delay time to do so. It must need to set the windows default printer in another way - as SET PRINTER TO NAME ThePrinterName is not doing the job. The VFP report goes to the right one, but the PDF sent by ShellExecute still goes to the original default printer - even though SET("Printer",3) has recognised the change. It's mildly frustrating so far...

Sorry about the long winded post - I would really be grateful for any advice you can offer...

Thanks

Karen
 
Well, the API is here for the rescue, once more. You can set the default pinter, use ShellExecute to print and then reset the default printer.

You just need SetDefaultPrinter and GetDefaultPrinter beforehand, if you want to set the default back:
[URL unfurl="true"]http://www.news2news.com/vfp/?function=940[/url]
[URL unfurl="true"]http://www.news2news.com/vfp/?function=548[/url]

Code:
DECLARE INTEGER GetDefaultPrinter IN winspool.drv;
 STRING @ pszBuffer,;
 INTEGER @ pcchBuffer

DECLARE INTEGER SetDefaultPrinter IN winspool.drv;
 STRING pszPrinter

lnBufferLen  = 100
lcOldPrinter = Space(lnBufferLen)
lcNewPrinter = "YOUR SUPER DUPER PRINTER HERE"

GetDefaultPrinter( @lcOldPrinter, @lnBufferLen )
lcOldPrinter = Left( lcOldPrinter, lnBufferLen-1 )
SetDefaultPrinter( lcNewPrinter)

ShellExecute(...) & print PDF

SetDefaultPrinter( lcOldPrinter)

Bye, Olaf.
 
Here is the routine I use to quickly and temporarily change printers.

It will temporarily change the workstation default printer to the desired one - <do whatever> - and then immediately set the default printer back.

NOTE - it does require that Windows Scripting be supported (installed if necessary) on the workstations

Code:
lcNewPrinter = "MyPrinter2"  && Or however the printer is named in Windows


* --- Determine Current Default Windows Printer ---
lcDefaultPrinter =  SET("PRINTER",2)

* --- Use APRINTERS() To Determine What Printers Available ---
=APRINTERS(gaPrinters)

nLoc = ASCAN(gaPrinters,lcNewPrinter)
IF nLoc > 0
  * --- Desired New Printer Exists, Use It ---

  * --- Use Windows Scripting To Set Default Printer To Specific Desited Printer ---
  ONET = CREATEOBJECT("WScript.Network")
  ONET.SetDefaultPrinter(lcNewPrinter)

  SET PRINTER TO NAME (lcNewPrinter)
ENDIF  && IF nLoc > 0

< do whatever >

* --- Immediately set workstation printer back to default ---

* --- When Done Printing - Use [B][U]Windows Scripting[/U][/B] To Restore Original Default Printer ---
ONET.SetDefaultPrinter(lcDefaultPrinter)
RELEASE ONET

SET PRINTER TO NAME (lcDefaultPrinter)

Obviously if you need to swap through 3 printers you can use the same routine to do so with some tweaking.

Good Luck,
JRB-Bldr
 
Thank you both Olaf and JRB-Bldr for your response.

I am not using scripting at this stage so Olaf's ShellExecute solution fits in perfectly with the PDF printing method I have chosen.

I appreciate your help, once again. A star for each of you to say Thanks.

Regards

Karen
 
Hi - Back again...

I am still having some problems printing the PDF to the desired printer.

I have set the default printer with SetDefaultPrinter( myprinter )
then printed the VFP report, that's fine...

But when I print the watermarked PDF it still goes to the previously selected default printer, even though I can see that the default is the newly selected printer.

I am using this code:

Code:
DECLARE INTEGER SetDefaultPrinter IN winspool.drv; 
	STRING pszPrinter

=SetDefaultPrinter( myPrinterName )

*...prints the report then calls a function to the pdf printing with...

DECLARE INTEGER ShellExecute IN shell32.dll ;
  INTEGER hndWin, ;
  STRING cAction, ;
  STRING cFileName, ;
  STRING cParams, ; 
  STRING cDir, ;
  INTEGER nShowWin
  
cFileName = myWMFile   && eg foldername\filename.pdf
cAction = "print"
nShowWin = 2
hndWin = 0
	
ShellExecute(hndWin,cAction,cFileName,"","",nShowWin)

I have tried ways around this including delaying the printing but the PDF still prints to the original default printer. This is an issue due to different printers having different stationery and is the same regardless of the computer speed.

Can parameters be used for "cParams" to specify the printer? I tried but it doesn't work - perhaps I don't have the correct format.

Can anyone help please?

Karen



 
But when I print the watermarked PDF it still goes to the previously selected default printer, even though I can see that the default is the newly selected printer.

Have you stopped program execution immediately after creating the PDF document and then from outside of VFP manually entered your PDF 'tool' to print out the document?

By doing a FILE - PRINT (or whatever menu choices you have) you should be able to see what output printer that application 'thinks' it is supposed to use as a default.

Could it be that the PDF 'tool' configuration has some stored/default printer setting within itself?

Or perhaps you will need to Close the PDF 'tool' and re-open it between the Create and Printout operations so that it can 'read' a new workstation default printer.

Good Luck,
JRB-Bldr
 
Actually, colleague Karen, SET PRINTER TO NAME should work in both of your cases.
I recall somebody telling that the abovementioned command actually does not change the WinOS's default printer, just the VFP's one.

OTOH, I recall myself using CommonDialog/Printer control (ComDlg32.OCX, ComCtl32.DLL, IMS) in my VFP/VS6 days for changing the WinOS's (Win95.N at the time) default printer, but that was for manual change, with GUI...

Anyway, HTH.

Another thought:
If these two printers have the same names for any user on the LAN (it is a LAN, isn't it?) you can make it as two different FRX-es with different saved printer environments each. Thus you could run the regular one and the the PDF-based one independently in any order - how's that for the idea? :)

Regards,

Ilya
 
If I might jump in here ....

I can't contribute anything new on this, except to say that I am dubious about changing the Windows default printer - even if you change it back as soon as you've finished with it. Your application is not the only one on the computer, and it's not reasonable to expect the user to refrain from doing any other printing while you are creating the PDF.

I feel sure there must be other ways of adding a watermark to a PDF (without necessarily adding it to the printed version).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Hi JRB-Bldr

Yes I have tried this and the printer selection is OK. This is an intermittent problem in that it will work sometimes and then stop working again.

~

Hi Ilya

Thank you - but it's one FRX and one PDF so I can't handle it that way. If I were to upgrade to VFP9 it could probably be done without PDFs but I'm still in VFP6

~

Hi Mike

I agree with you, changing the default printer could affect work processing and other tasks.

This is one of those last minute items added to a job - you know the ones - that turns out to take as much time as the main job. Just to add a watermark...

~

I may revert to a simple bold message at the top and bottom of the page instead of the diagonal text FILE COPY image, at least for the time being.

Oh well - You win some....

Thank you.

Regards

Karen
 
Then, I've probably misread something in your post, Karen:
Is it FRX report we're talking about? (Like, made in VFP with Report Builder?) Or it is just some text (ASCII, RTF, DOC format, etc.) that you need to print?


Regards,

Ilya
 
ShellExecute does not wait for the executed application to finish, so you might have turned back to the original default printer, before Acrobat reader or whatever is configured for PDFs is printing.

You could wait a bit, before resetting the default prinert, or you could also try cPArams indeed. In this thread about Acrobat Reader you find some hints on it's parameterisation:

The way you'd Shellexecute Acrobat.exe or Acrord32.exe instead of the PDF file, and specify both file name and printer as parameters in one cParams string. You could also try RUN:

RUN /N AcroRd32.exe /t "d:\pdffiles\yourfile.pdf" "your printer"

Bye, Olaf.
 
There's also ShellExecuteEx() function (see and which is supposed to execute and wait for the completion of the program.

It is somewhat cumbersome to translate the C/C++ structure data type to VFP to use as a parameter in the call to this function (so I had my C programmer to make a DLL for us to use similar functions in the VFP apps), but it can be done.


Regards,

Ilya
 
Did it help, and what did?

Another though: Instead of waiting "a bit", you could read print jobs for the printer and see, if your pdf document is in the queue before resetting default printer.

Sergey Bereziker has some code to read the printer queues via WMI or Windows API here: www.berezniker.com/content/pages/visual-foxpro/enumerating-jobs-print-queue

Bye, Olaf.
 
....you would repeatedly query print jobs and wait with resetting the default printer, until your pdf document name shows up in loPrintjob.Document (WMI code) or loOneJob.Document (API code).

Bye, Olaf.



 
Hi all.

Olaf - your RUN command solution is great because it means that I don't have to change default printers at all.

After a bit more digging I found more /switch settings at
So I have used the following:

Code:
mRunCmd = "RUN /N c:\path\+AcroRd32.exe /n /h /t "+mFileName+" "+mPrinterName
&mRunCmd

/n Launches a new instance of the reader
/h Is meant to open as a minimized window
/t Handles the printing of FileName to PrinterName

I have not specified driver name or port name.

This is working at the moment but will leave one instance of Acrobat open.

As I have since seen your other posts, Olaf and Ilya, I will run through these and come back with the final solution.

Thanks again for your replies.

Karen
 
Hi again

I didn't go any further into ShellExecute but the PDF printing is now working and I can also close the Acrobat window using the following code:

Code:
*- mPDFReader is the full path\name for Acrobat
*  E.G. C:\Program Files\Adobe\reader 8.0\Reader\AcroRd32.exe
*
*- mWMCopy is the full path\file name for the watermarked PDF
*  E.G. C:\TempVFP\Inv12345_FileCopy.PDF
*
*- mPrtTo is the printer name
*  E.G. \\Computer\PrinterName or just PrinterName
*

WAIT WINDOW 'Printing the File Copy...' NOWAIT

*- Create and RUN command line
mPDFComm = 'RUN /N '+mPDFReader+' /t '+mWMCopy+' '+mPrtTo
&mPDFComm

*- Delay a little
WAIT WINDOW 'Printing the File Copy...' TIMEOUT 5

*- Find the Adobe window
Declare Long FindWindow in User32 ;
   String cClassname, String cTitle

*  NB the window name includes the file name 
*  E.G. "inv12345_filecopy.pdf - Adobe Reader"
hWnd = FindWindow(Null, LOWER(JUSTFNAME(mWMCopy))+' - Adobe Reader')

*- Now close it
Declare Long SendMessage in User32 ;
   Long nhWnd, Long Msg, Long wParam, Long lParam
SendMessage(hWnd, 0x10, 0, 0)

Thank you very much for your help once again.

Karen
 
Just watch out, if paths contain spaces, you shoul put them into quotes within mPDFComm, so do:

Code:
mPDFComm = [RUN /N "]+mPDFReader+[" /t "]+mWMCopy+[" "]+mPrtTo+["]

Not sure about putting the printer name into quotes. But as you say this could be a unc path to the printer, this should also work.

Bye, Olaf.
 
Thank you, Olaf.

That is bound to come up sooner or later.

Kind regards

Karen
 
I have a problem very similar to this post, and have used Olaf's suggestion for the code to try and solve it. It appears to solve my timing problem (was using ShellExecute) with one more problem. It opens Acrobat Reader, prints the file, closes the file, but leaves Acrobat Reader open. Can you help me past the goal?

Code:
lnOrientation=0  && Portrait
lnPaperSize=1    && Letter (8 1/2 x 11")
lnCopies = 1
    
Select netprint
Seek tcPrinter
If Found() THEN
	lcPName = Alltrim(netprint.queue)
Else
	Do WRITELOG With "[ERR] Printer name invalid -" + lcPrinter
	COPY TO ('c:\printerlist.csv') TYPE DELIMITED
	DO SIMPEM01 WITH "wilbiradmin@winnebagoind.com", "dba@winnebagoind.com", "Printer not mapped correctly in PRTPDF01", "", "", "KA", "c:\printerlist.csv"
	llError = .T.
Endif

FOR X = 1 TO tnCopies
	mPDFReader = "C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe"
	mWMCopy = (lcFName)
	mPrtTo = (lcPName)
	
	*- Create and RUN command line
mPDFComm = [RUN /N "]+mPDFReader+[" /t "]+mWMCopy+[" "]+mPrtTo+["]
&mPDFComm

*- Delay a little
WAIT WINDOW 'Printing the PDF File...' TIMEOUT 5

*- Find the Adobe window
Declare Long FindWindow in User32 ;
   String cClassname, String cTitle

*  NB the window name includes the file name 
hWnd = FindWindow(Null, LOWER(JUSTFNAME(mWMCopy))+[" - Adobe Reader"])

*- Now close it
Declare Long SendMessage in User32 ;
   Long nhWnd, Long Msg, Long wParam, Long lParam
SendMessage(hWnd, 0x10, 0, 0) 

If lcPurge = .T. AND lcFname = lcFname1
	IF FILE(lcFname)
		DELETE FILE(lcFname)
	ENDIF 
ENDIF
NEXT
RETURN lcRecType
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top