×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Using ShellExecute to print a PDF to specific printer
2

Using ShellExecute to print a PDF to specific printer

Using ShellExecute to print a PDF to specific printer

(OP)
Hi Gurus

With reference to so many threads (thread184-698845: printing a pdf within a foxpro app. withour previewing, thread184-1485500: Acrobat Reader and ShellExecute and thread184-1485500: Acrobat Reader and ShellExecute 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

RE: Using ShellExecute to print a PDF to specific printer

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:
http://www.news2news.com/vfp/?function=940
http://www.news2news.com/vfp/?function=548

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.

RE: Using ShellExecute to print a PDF to specific printer

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 Windows Scripting 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

RE: Using ShellExecute to print a PDF to specific printer

(OP)
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

RE: Using ShellExecute to print a PDF to specific printer

(OP)
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



RE: Using ShellExecute to print a PDF to specific printer

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

RE: Using ShellExecute to print a PDF to specific printer

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? smile

Regards,

Ilya

RE: Using ShellExecute to print a PDF to specific printer

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

RE: Using ShellExecute to print a PDF to specific printer

(OP)
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

RE: Using ShellExecute to print a PDF to specific printer

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

RE: Using ShellExecute to print a PDF to specific printer

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:
http://www.vbaexpress.com/forum/archive/index.php/...

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.

RE: Using ShellExecute to print a PDF to specific printer

There's also ShellExecuteEx() function (see http://msdn.microsoft.com/en-us/library/bb762154(V... and http://msdn.microsoft.com/en-us/library/bb759784(v...) 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

RE: Using ShellExecute to print a PDF to specific printer

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.

RE: Using ShellExecute to print a PDF to specific printer

....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.



RE: Using ShellExecute to print a PDF to specific printer

(OP)
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 http://stackoverflow.com/questions/619158/adobe-re...

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

RE: Using ShellExecute to print a PDF to specific printer

(OP)
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

RE: Using ShellExecute to print a PDF to specific printer

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.

RE: Using ShellExecute to print a PDF to specific printer

(OP)
Thank you, Olaf.

That is bound to come up sooner or later.

Kind regards

Karen

RE: Using ShellExecute to print a PDF to specific printer

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 

RE: Using ShellExecute to print a PDF to specific printer

I don't see you using ShellExecute here, you use RUN.

With Shellexecute you can determine tthe action "open" or "print" with the PDF file and if you Shellexecute a PDF with the "print" action it should print and not leave the PDF reader open.

Otherwise you need to use soem API to kill the process, eg use SendMessage with the hWnd you use to quit the application.

It seems SendMessage(hWnd, 0x10, 0, 0) shoudl do that. Try 0x12 insread, WM_QUIT. 0x10 is WM_CLOSE.

Bye, Olaf.

RE: Using ShellExecute to print a PDF to specific printer

Quote (Olaf)

With Shellexecute you can determine tthe action "open" or "print" with the PDF file and if you Shellexecute a PDF with the "print" action it should print and not leave the PDF reader open.

Actually, I have found that using ShellExecute() with "print" does leave the reader open. I couldn't find any easy solution to that. The only good thing is that, if you do multiple calls (that is, to print several different PDFs), only one instance is opened, but that doesn't solve the problem.

It was several years ago that I did this, so it's possible that things have changed with more recent versions.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy

RE: Using ShellExecute to print a PDF to specific printer

Well, I didn't tried. I just remembered Word called with "print" action would really just print and then quit again, as soon as the print job is done and the spooler is fed, but I may also be wrong about that.

There would always be the option to use WMI to find a process of any exe and KillProcess, eg see http://www.berezniker.com/content/pages/visual-fox...

Bye, Olaf.

RE: Using ShellExecute to print a PDF to specific printer

I am testing as we speak but what I have found to work is...

CODE -->

* find its hwnd
DECLARE INTEGER FindWindow IN user32;
    STRING lpClassName, STRING lpWindowName

nHwnd = FindWindow(NULL, "Adobe Reader")
DECLARE INTEGER ShowWindow IN user32;
    INTEGER hwnd,;
    INTEGER nCmdShow
ShowWindow(nHwnd, 0)

DDEChan = DDEInitiate("Acroview", "Control")
=DDEExecute(DDEChan, '[CloseAllDocs()]')
=DDEEXECUTE(ddechan,'[AppExit]')

CLEAR DLLS [FindWindow, ShowWindow] 

Added this to the end of the code and it now will close the program. (This is from parts of code you guys helped me with a couple years ago.)

You are right Olaf, I have abandoned the ShellExecute in favor of Run because if the Reader did not get shut down (or is not yet down) when the next process calling for the Reader fires, it hangs the application. With Run, it will continue on its happy way and use the open program.

RE: Using ShellExecute to print a PDF to specific printer

I was just about to think of and mention I may have confused the ShellEecute "print" action with a similar DDE print action sent to Word or another app via DDE. It actually is closely related, as the shellexec actions are DDE actions, but you hvae some DDE functions in foxpro, too.

Glad you already found DDEEXEC in your knowledgebase, too.

Bye, Olaf.

RE: Using ShellExecute to print a PDF to specific printer

Quote:

I just remembered Word called with "print" action would really just print and then quit again, as soon as the print job is done and the spooler is fed, but I may also be wrong about that.

I would think that would be normal behaviour for most applications. It's just the Acrobat viewer that has this problem, as far as I know.

Pat: Interesting that it works with DDEExecute(). I wouldn't have thought of that.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close