Sign in to follow this  
Followers 0
JeffL

Silent PDF print in Adobe Reader 9.1

15 posts in this topic

#1 ·  Posted (edited)

I'm really stumped here. I feel like i've tried everything. Basically I wrote a script to run through a mailbox and print out all attachments of a certain document type. The other documents work, but not PDFs via Adobe Reader. It works via Foxit, but I'm the only one that uses this and it is a script for other people.

What I tried to run originally was:

ShellExecuteWait($sFilePath, "", "", "print", @SW_HIDE)

but Reader doesn't close when complete so it Waits indefinitely.

I tried some switches such as

ShellExecuteWait($sFilePath, " /h /p", "", "print", @SW_HIDE)

but no differing behavior and through my research, I am led to believe it is the Reader version suppressing this silent print behavior.

The main problem here is that it NEEDS to wait for the process to complete or it won't print at all, but it also needs to close Reader. So I looked for methods for waiting for the print...

I got this function working:

func getPrintInfo($sFileName, $sInfo)
    ;$sinfo = caption,host,id,owner
    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PrintJob", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    if IsObj($colItems) then
        for $objItem In $colItems
            if $objItem.Document = $sFileName then
                switch $sInfo
                    Case "caption"
                        return $objItem.Caption
                    Case "host"
                        return $objItem.HostPrintQueue
                    Case "id"
                        return $objItem.JobId
                    Case "owner"
                        return $objItem.Owner
                endswitch
            endif
        next
    endif
    return 0
endfunc

Then did some while loops to see when the job existed in the queue or not. The output works if you pause a job and do the query, but it fails in my implementation and i have a feeling the print job is not even popping into the queue long enough for a successful query.

Then I tried:

ProcessWait("AcroRd32.exe", 5)
ProcessClose("AcroRd32.exe")

But again it kills the print with the process before it can begin.

I'm completely stumped. Obviously I could just put a regular Sleep after the ShellExecute, but I want as clean a method as possible for this, but it seems like I'm getting intercepted at every turn.

Anyone? :\

Edited by JeffL

Share this post


Link to post
Share on other sites



Not 100% sure what this function does, maybe polls the print service or print queue?

Couldn't you do a do/until calling the function

do

     getPrintInfo($sFileName, $sInfo)
     ; sleep 100 if it loops through to quickly

until return = 0

ProcessClose("AcroRd32.exe")

I'm really stumped here. I feel like i've tried everything. Basically I wrote a script to run through a mailbox and print out all attachments of a certain document type. The other documents work, but not PDFs via Adobe Reader. It works via Foxit, but I'm the only one that uses this and it is a script for other people.

What I tried to run originally was:

ShellExecuteWait($sFilePath, "", "", "print", @SW_HIDE)

but Reader doesn't close when complete so it Waits indefinitely.

I tried some switches such as

ShellExecuteWait($sFilePath, " /h /p", "", "print", @SW_HIDE)

but no differing behavior and through my research, I am led to believe it is the Reader version suppressing this silent print behavior.

The main problem here is that it NEEDS to wait for the process to complete or it won't print at all, but it also needs to close Reader. So I looked for methods for waiting for the print...

I got this function working:

func getPrintInfo($sFileName, $sInfo)
    ;$sinfo = caption,host,id,owner
    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PrintJob", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

    if IsObj($colItems) then
        for $objItem In $colItems
            if $objItem.Document = $sFileName then
                switch $sInfo
                    Case "caption"
                        return $objItem.Caption
                    Case "host"
                        return $objItem.HostPrintQueue
                    Case "id"
                        return $objItem.JobId
                    Case "owner"
                        return $objItem.Owner
                endswitch
            endif
        next
    endif
    return 0
endfunc

Then did some while loops to see when the job existed in the queue or not. The output works if you pause a job and do the query, but it fails in my implementation and i have a feeling the print job is not even popping into the queue long enough for a successful query.

Then I tried:

ProcessWait("AcroRd32.exe", 5)
ProcessClose("AcroRd32.exe")

But again it kills the print with the process before it can begin.

I'm completely stumped. Obviously I could just put a regular Sleep after the ShellExecute, but I want as clean a method as possible for this, but it seems like I'm getting intercepted at every turn.

Anyone? :\

Share this post


Link to post
Share on other sites

I've also created a script to print PDF's from a mailbox. (I wasn't able to create a full silent print).

But I came up with the following:

ShellExecuteWait ("C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" ,"/t " & $tempdir & $file & " " & $PrinterName, @SW_MINIMIZE)
WinWait($file,"")
Winwait("Adobe Reader")

When Acrobat Reader prints the file (commandline switch: "/t") the windowtitle of adobe Reader changes to the filename, when the print is completed/queued it changes back to "Adobe Reader". At that point it's safe to continue you're code.

(I use winkill to close de AcroRd32.exe)

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

You can use DDE printing.

HTH, Reinhard

#include <DDEML.au3>         ;<= load down from examples
#include <DDEMLClient.au3>   ;<= load down from examples


$FnToPrt = "C:\Test.pdf"

ShellExecute("AcroRD32.exe","/h")
Opt("WinTitleMatchMode", 2)
WinWait("Reader","",10)
sleep(500)
$szService = "Acroview"
$szTopic = "Control"
$szCommand = '[FilePrintSilent("'&$FnToPrt&'")][AppExit()]'
_DDEMLClient_Execute($szService, $szTopic, $szCommand)
Edited by ReFran

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

the logic here is sound but the execution gives me the same results. processclose("acrord32.exe") kills adobe before it can send the job to the print queue. not sure why....

if i put a msgbox or sleep before the process close, itll print

I've also created a script to print PDF's from a mailbox. (I wasn't able to create a full silent print).

But I came up with the following:

ShellExecuteWait ("C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" ,"/t " & $tempdir & $file & " " & $PrinterName, @SW_MINIMIZE)
WinWait($file,"")
Winwait("Adobe Reader")

When Acrobat Reader prints the file (commandline switch: "/t") the windowtitle of adobe Reader changes to the filename, when the print is completed/queued it changes back to "Adobe Reader". At that point it's safe to continue you're code.

(I use winkill to close de AcroRd32.exe)

Edited by JeffL

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I have no idea what DDE is, but this worked! Thank you!

I'll have to do some studying up on this UDF.

You can use DDE printing.

HTH, Reinhard

#include <DDEML.au3>         ;<= load down from examples
#include <DDEMLClient.au3>   ;<= load down from examples


$FnToPrt = "C:\Test.pdf"

ShellExecute("AcroRD32.exe","/h")
Opt("WinTitleMatchMode", 2)
WinWait("Reader","",10)
sleep(500)
$szService = "Acroview"
$szTopic = "Control"
$szCommand = '[FilePrintSilent("'&$FnToPrt&'")][AppExit()]'
_DDEMLClient_Execute($szService, $szTopic, $szCommand)

Edited by JeffL

Share this post


Link to post
Share on other sites

I have no idea what DDE is, but this worked! Thank you!

I'll have to do some studying up on this UDF.

DDE is an older method for interapplications communication (before ActiveX).

You can work with that for example in the File associations.

So you can do a little bit more then only command line option.

Adobe complicate in every new version the using of Javascript and ActiveX because of security reasons.

But they didn't touch old DDE for years. So DDE printing is treated as the only reliable method for silent/hidden printing using Reader, if you want to close after printing.

Another method, according to your first post, would be to check only if printing startet:

if Winexists('CLASS:PrintUI_PrinterQueue]',"")=0 then

;msgbox(0,"","printing")

WinClose($Readerhandle)

endif

If printing startet you can Reader ask to close (Winclose).

Reader will only close if printing is finished.

If you interested in this method I may extract the complete code/loop from a bigger script.

best regards, Reinhard

Share this post


Link to post
Share on other sites

DDE is an older method for interapplications communication (before ActiveX).

You can work with that for example in the File associations.

So you can do a little bit more then only command line option.

Adobe complicate in every new version the using of Javascript and ActiveX because of security reasons.

But they didn't touch old DDE for years. So DDE printing is treated as the only reliable method for silent/hidden printing using Reader, if you want to close after printing.

Another method, according to your first post, would be to check only if printing startet:

if Winexists('CLASS:PrintUI_PrinterQueue]',"")=0 then

;msgbox(0,"","printing")

WinClose($Readerhandle)

endif

If printing startet you can Reader ask to close (Winclose).

Reader will only close if printing is finished.

If you interested in this method I may extract the complete code/loop from a bigger script.

best regards, Reinhard

Thanks for that last tip as well. I tried doing that with my function that queried the print queue, but couldnt get it to work. Is PrintUI_PrinterQueue the notification bubble that pops up when a print has been sent?

Share this post


Link to post
Share on other sites

... Is PrintUI_PrinterQueue the notification ....

Yes and it closes automatic is print job is done.

Excuse the delay. I work in a finance department

and we are on the way to finalise our closing.

Attached an quick example, extracted from an older, big script.

But DDE should work better.

best regards, Reinhard

Opt("WinTitleMatchMode", 2)
$FnToPrt = "C:\Test.pdf"

ShellExecute("AcroRD32.exe","/h /p"&" """&$FnToPrt&"""" ,"","", @SW_HIDE )
$OK = ProcessWait("AcroRd32.exe",20)
if $OK = 0 Then
    msgbox(0,"","Coudn't start process")
    ;return 0
    exit
endif   

GLOBAL $PID = WinGetProcess ("Reader")
GLobal $handle = WinGethandle ("Reader")
$timer = 0      
Do
    sleep(1000)
    $timer +=+1
    if Winexists('[CLASS:PrintUI_PrinterQueue]',"")=0 then
        ;msgbox(0,"","Printing finished")
        WinClose($handle)
    endif
    if $timer = 60 then
        msgbox(0,"","Timeout")
        ;return 0
        exitloop
    endif
until ProcessExists($PID) = 0

Share this post


Link to post
Share on other sites

You can use DDE printing.

HTH, Reinhard

#include <DDEML.au3>         ;<= load down from examples
#include <DDEMLClient.au3>   ;<= load down from examples


$FnToPrt = "C:\Test.pdf"

ShellExecute("AcroRD32.exe","/h")
Opt("WinTitleMatchMode", 2)
WinWait("Reader","",10)
sleep(500)
$szService = "Acroview"
$szTopic = "Control"
$szCommand = '[FilePrintSilent("'&$FnToPrt&'")][AppExit()]'
_DDEMLClient_Execute($szService, $szTopic, $szCommand)

How would you structure the $szCommand to specify the printer to be used?

Share this post


Link to post
Share on other sites

Hello.

Full silent pdf print example. You need Foxit Reader only.

$def = RegRead("HKCU\Software\Microsoft\Windows Nt\CurrentVersion\Windows", "Device")

$printer = "HP Color LaserJet CP1215,winspool,Ne01:"
RegWrite("HKCU\Software\Microsoft\Windows Nt\CurrentVersion\Windows", "Device", "REG_SZ", $printer)

$file = "C:\a.pdf"
RunWait('C:\Program Files\Foxit Software\Foxit Reader\Foxit Reader.exe /p "' & $file & '"')
RegWrite("HKCU\Software\Microsoft\Windows Nt\CurrentVersion\Windows", "Device", "REG_SZ", $def)

Enjoy :blink:

Share this post


Link to post
Share on other sites

I tried the DDE example and got a ton of errors. Then I updated my AutoIt installation and still had a ton until I commented out the two includes. Now I only get one error but I can't find anything on it when I search. Here's my code and the error message.

;#include <DDEML.au3>   ;<= load down from examples
;#include <DDEMLClient.au3> ;<= load down from examples
$FnToPrt = "x:\Temp2\1.pdf"
ShellExecute("C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Acrobat.exe","/h")
Opt("WinTitleMatchMode", 2)
WinWait("Acrobat","",10)
sleep(500)
$szService = "Acroview"
$szTopic = "Control"
$szCommand = '[FilePrintSilent("'&$FnToPrt&'")][AppExit()]'
_DDEMLClient_Execute($szService, $szTopic, $szCommand)
Exit
---------------------------------------------------------------------------------------

ERROR: _DDEMLClient_Execute(): undefined function.
_DDEMLClient_Execute($szService, $szTopic, $szCommand)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

For me it works furtheron:

AdobeReader v9.3 / AutoIt v3.3.5.3 (beta)

Because I saved a backup I made a textcomparison:

in DDEML.au3 I changed line 604:

from: If @ProcessorArch = "IA64" Or @ProcessorArch = "X64" Then $res = 64

to: If @autoItx64 = 1 Then $res = 64

HTH, Reinhard

Edited by ReFran

Share this post


Link to post
Share on other sites

Hmm, I didn't have that on my line 604, then I downloaded the latest version and it's not on line 604 there either. In fact, $ProcessorArch isn't even found in the file!

However, the latest version of ddeml.au3 did fix the problem I was having, I must have clicked on the wrong download link when I got the include file. Now the problem is that the DDE command still fails once in a while (no error message, it just doesn't print). I have Adobe Acrobat Pro instead of the Reader so maybe that's the issue.

The first time I run the app, it flashes an Acrobat window then minimizes it - nothing prints.

The next time I run the app, the Acrobat window does NOT minimize - but it prints!

If I remove the "/h" parameter from the shellexecute, it doesn't minimize - and nothing prints.

I give up. I'll just put a send('^p{enter}') in and sleep for a few seconds.

Share this post


Link to post
Share on other sites

Hi,

DDE printing should work for Acrobat Pro and Reader, like the command-line option.

However if you want to print via AcrobatPro you can use ActiveX, how it is described in the SKD (Interapplication Communication = IAC section).

Attached a script which should do what you want (for AcrobatPro).

HTH, Reinhard

$fileIn = "C:\Test.pdf"              ;; state the full path of the file to print
$App = ObjCreate("AcroExch.App")     ;; start Adobe Acrobat
;$App.Show                           ;; show Acrobat or comment out for hidden mode

$AVDoc = ObjCreate("AcroExch.AVDoc") ;; connect to Ac Viewer
$AVDoc.Open($fileIn,"")              ;; Open a file into viewer
$PDDoc = $AVDoc.GetPDDoc             ;; Get the Doc opened in the viewer
$JSO = $PDDoc.GetJSObject            ;; Connect to Acrobat JS
$JSO.app.alert("Hi, file is open.Press Ok for printing")  ;; Display a MsgBox
;$JSO.print("bUI","nStart","nEnd","bSilent","bShrinkToFit",..)
$nEnd=$jso.numPages-1 ;;$nEnd zeroBase
$JSO.print(False,0,$nEnd,False,True)   ;; print with some options
$JSO.closeDoc(True)     ;; close active document

$App.CloseAllDocs               ;; - or - close all docs
$App.exit

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0