How to implement batch print pdf file programmatically

  • Follow


I'm a newbie to PDF related Programming. Now I want to implement a
function : given a batch of pdf files which may be located locally or
on some place in the network pionted to by a URL. Once scheduled a task
and submit it, then I can wait for these to be printed. For this
target, I surfed on the web, but can't find a library or product that
suit my need and free from charge, and also full granted license for
any purpose and can be use evreywhere? Can anyone give me a hint  to
implement this function and any related library which can has
implemented related function and only little effor need to fulfill the
ultimate task and no commercial-usage limitation. And My preferred
language is C++ or Java. Thanks a lot.

0
Reply Audison.Athena (10) 7/27/2006 12:53:08 PM

This is a multi-part message in MIME format.
--------------020702050705010702000306
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

You can use Ghostscript to print PDF files from the command line.

gswin32c.exe -dNOSAFER -dNOPAUSE -dBATCH -sDEVICE=mswinpr2 
-sOutputFile="\\spool" "c:\myfile.pdf"

You can also do that with the Ghostscript-API (gsdll32.dll, you should 
find C++ examples on the Ghostscript website).

As alternative, you can print PDFs with the Adobe Reader in two ways:

1.) Via Command Line
start acrord32.exe /p /h c:\test.pdf
Unfortunately the Adobe Reader doesn't close itself after printing.

2.) Via DDE
I attached a VB6-Module which does exactly that. Porting that to C++ 
shuoldn't be a problem.

Regards

Marcus


Audison.Athena@gmail.com schrieb:
> I'm a newbie to PDF related Programming. Now I want to implement a
> function : given a batch of pdf files which may be located locally or
> on some place in the network pionted to by a URL. Once scheduled a task
> and submit it, then I can wait for these to be printed. For this
> target, I surfed on the web, but can't find a library or product that
> suit my need and free from charge, and also full granted license for
> any purpose and can be use evreywhere? Can anyone give me a hint  to
> implement this function and any related library which can has
> implemented related function and only little effor need to fulfill the
> ultimate task and no commercial-usage limitation. And My preferred
> language is C++ or Java. Thanks a lot.
> 


--------------020702050705010702000306
Content-Type: text/plain;
 name="modPrintPDF.bas"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="modPrintPDF.bas"

Attribute VB_Name = "modPrintPDF"
Option Explicit

' Get Reader PID Workstation
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Sub CloseHandle Lib "kernel32" (ByVal hPass As Long)
' Get Reader PID Terminal Server
Private Declare Function WTSEnumerateProcesses Lib "wtsapi32.dll" Alias "WTSEnumerateProcessesA" (ByVal hServer As Long, ByVal Reserved As Long, ByVal Version As Long, ByRef ppProcessInfo As Long, ByRef pCount As Long) As Long
Private Declare Sub WTSFreeMemory Lib "wtsapi32.dll" (ByVal pMemory As Long)
' Get process name
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (lpString1 As Any, lpString2 As Any) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (lpString As Any) As Long
' Get Reader path
Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
' Get Reader HWND
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
' Hide Reader Window
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Const GWL_EXSTYLE = (-20)
Private Const LWA_ALPHA = &H2
Private Const WS_EX_LAYERED = &H80000

Private Const TH32CS_SNAPPROCESS As Long = 2&
Private Const MAX_PATH As Integer = 260
Private Const WTS_CURRENT_SERVER_HANDLE = 0&

Private Const SW_HIDE = 0
Private Const SWP_HIDEWINDOW As Long = &H80&

Private Type PROCESSENTRY32
    dwSize As Long
    cntUsage As Long
    th32ProcessID As Long
    th32DefaultHeapID As Long
    th32ModuleID As Long
    cntThreads As Long
    th32ParentProcessID As Long
    pcPriClassBase As Long
    dwFlags As Long
    szExeFile As String * MAX_PATH
End Type

Private Type WTS_PROCESS_INFO
    SessionID As Long
    ProcessId As Long
    pProcessName As Long
    pUserSid As Long
End Type

Dim ReaderPID As Long
Dim ReaderhWnd As Long

Public Function PrintFile(ByVal InFile As String, Optional ByVal PrinterName As String) As Boolean
Dim Result As String
    
    Result = GetqvPDFKeyValue("PrintingSystem")
    Select Case Result
        Case "1"
            PrintFile = PrintFile_Reader(InFile, PrinterName)
        Case Else
            PrintFile = PrintFile_GS(InFile, PrinterName)
    End Select
End Function

Private Function PrintFile_GS(ByVal InFile As String, Optional ByVal PrinterName As String) As Boolean
Dim ProfileString As String
Dim astrArgs() As String

    If FileExists(InFile) Then
        ProfileString = "-dNOSAFER -dNOPAUSE -dBATCH -dNoCancel -sDEVICE=mswinpr2"
        If (PrinterName = Empty) Then
            PrinterName = """\\spool"""
            ProfileString = ProfileString & " -dQueryUser=3"
        Else
            PrinterName = "\\spool\" & PrinterName & ""
        End If
        
        astrArgs = GSProfileStringToArray(ProfileString, InFile, PrinterName)
        CallGS astrArgs
        PrintFile_GS = True
    End If
End Function

Private Function PrintFile_Reader(ByVal InFile As String, Optional ByVal PrinterName As String) As Boolean
'On Error GoTo ErrorHandler
Dim ReaderPath As String
Dim CloseReader As Boolean
Dim lRet As Long

    ' Check if Adobe Reader is already running. We must determine between workstation and terminal server
    ' as ProcessFirst/ProcessNext also returns processes from other sessions when running a session
    ' in an administrators context! DDE commands can only be sent to a Reader instance in the same session.
    
    If (IsTerminalServer = True) Then
        ReaderPID = GetReaderPID_TS
    Else
        ReaderPID = GetReaderPID
    End If
    
    If (ReaderPID = 0) Or (ReaderDDEResponsive = False) Then
        'No active DDE responsive Adobe Reader found in this session! Start one!
        ReaderPath = GetReaderPath(InFile)
        ReaderPID = Shell(ReaderPath, vbHide)
        If (ReaderPID > 32) Then
            CloseReader = True
            GetReaderhWnd ' Get hwnd of Adobe Reader
            Sleep 1000 ' Wait for a second to make sure Adobe Reader is responsive
        End If
    End If
    
    If (ReaderPID > 0) Then
            If (CloseReader = True) Then
                ShowWindow ReaderhWnd, SW_HIDE ' Hide Adobe Reader
                MakeTransparent ReaderhWnd, 0 ' Damn Bitch
            End If
            If (PrinterName = Empty) Then
                ' Print on Windows default printer
                SendDDEMessage "acroview", "control", "[FilePrintSilent(""" & InFile & """)]"
            Else
                SendDDEMessage "acroview", "control", "[FilePrintTo(""" & InFile & """, """ & PrinterName & """, """", """")]"
            End If
            If (CloseReader = True) Then
                ShowWindow ReaderhWnd, SW_HIDE ' Hide Adobe Reader
                Sleep 1000 ' Wait for a second...again
                SendDDEMessage "acroview", "control", "[AppExit]"
            End If
            PrintFile_Reader = True
    Else
        PrintFile_Reader = False
    End If
    Exit Function
ErrorHandler:
    PrintFile_Reader = False
End Function

Private Function GetReaderPID() As Long
' On Local Error Resume Next
' Checks if AcroRd32.exe is running and returns the PID
Dim hSnapShot As Long
Dim Result As Long
Dim ProcessEXEName As String
Dim Process As PROCESSENTRY32

    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0&)
    If hSnapShot <> 0 Then
        Process.dwSize = Len(Process)
        Result = ProcessFirst(hSnapShot, Process)
        Do While Result <> 0
            ProcessEXEName = Process.szExeFile
            ' Um den vollen Pfadnamen unter Windows NT basierenden Systemen
            ' auszulesen, siehe http://support.microsoft.com/support/kb/articles/Q187/9/13.asp.
            ProcessEXEName = LCase(Left$(ProcessEXEName, InStr(ProcessEXEName, Chr$(0)) - 1))
            If ProcessEXEName = "acrord32.exe" Then
                GetReaderPID = Process.th32ProcessID
                Exit Do
            End If
            Result = ProcessNext(hSnapShot, Process)
        Loop
        Call CloseHandle(hSnapShot)
    End If
End Function

Private Function GetReaderPID_TS() As Long
' On Local Error Resume Next
' Checks if AcroRd32.exe is running and returns the PID
Dim lCount As Long
Dim I As Long
Dim qvPDF_PID As Long
Dim lpBuffer As Long
Dim lp As Long
Dim lSID As Long
Dim udtProcessInfo As WTS_PROCESS_INFO
        
    qvPDF_PID = GetCurrentProcessId
    If WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0&, 1, lpBuffer, lCount) Then
        ' Get the current SessionID
        lp = lpBuffer
        For I = 1 To lCount
            CopyMemory udtProcessInfo, ByVal lp, LenB(udtProcessInfo)
            If (qvPDF_PID = udtProcessInfo.ProcessId) Then
                lSID = udtProcessInfo.SessionID
                Exit For
            End If
            lp = lp + LenB(udtProcessInfo)
        Next
        
        ' Get AcroRD32-PID in this Session
        lp = lpBuffer
        For I = 1 To lCount
            CopyMemory udtProcessInfo, ByVal lp, LenB(udtProcessInfo)
            If (udtProcessInfo.SessionID = lSID) And (LCase(GetStrFromPtrA(udtProcessInfo.pProcessName)) = "acrord32.exe") Then
                GetReaderPID_TS = udtProcessInfo.ProcessId
                Exit For
            End If
            lp = lp + LenB(udtProcessInfo)
        Next
        WTSFreeMemory lpBuffer
    End If
End Function

Private Sub GetReaderhWnd()
    Call EnumWindows(AddressOf EnumWindowsProc, -1)
End Sub

Private Function ReaderDDEResponsive() As Boolean
    ReaderDDEResponsive = (SendDDEMessage("acroview", "control", "") = ExDdeError_Success)
End Function

Public Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
Dim TestPID As Long
Dim WindowText As String
  
    GetWindowThreadProcessId hWnd, TestPID
    If TestPID = ReaderPID Then
        ReaderhWnd = hWnd
        WindowText = Space$(256)
        GetWindowText hWnd, WindowText, Len(WindowText)
        If (InStr(WindowText, "Reader") > 0) Then
            ReaderhWnd = hWnd
            EnumWindowsProc = 0
            Exit Function
        End If
    End If
    EnumWindowsProc = 1
End Function

Private Function GetStrFromPtrA(lpszA As Long) As String
On Local Error Resume Next

    GetStrFromPtrA = String$(lstrlen(ByVal lpszA), 0)
    Call lstrcpy(ByVal GetStrFromPtrA, ByVal lpszA)
End Function

Private Sub MakeTransparent(ByVal hWnd As Long, Percentage As Integer)
On Error Resume Next
Dim Style As Long

    If ((Percentage >= 0) And (Percentage <= 255)) Then
        Style = GetWindowLong(hWnd, GWL_EXSTYLE)
        Style = Style Or WS_EX_LAYERED
        SetWindowLong hWnd, GWL_EXSTYLE, Style
        SetLayeredWindowAttributes hWnd, 0, Percentage, LWA_ALPHA
    End If
End Sub

Public Function GetReaderPath(Optional ByVal PDF_FilePath As String) As String
On Local Error Resume Next
Dim Result As String
Dim ReaderPath As String
Dim TempPDFFileCreated As Boolean

    Result = GetqvPDFKeyValue("ReaderPath")
    If (Result = Empty) Then
        If Not FileExists(PDF_FilePath) Then
           PDF_FilePath = GetTempFileName & ".pdf"
           WriteLogFile PDF_FilePath, Empty
           TempPDFFileCreated = True
        End If
        ReaderPath = String(MAX_PATH, 32)
        FindExecutable PDF_FilePath, vbNullString, ReaderPath
        GetReaderPath = ReaderPath
        If (TempPDFFileCreated = True) Then
            DeleteFile PDF_FilePath
        End If
    Else
        GetReaderPath = Result
    End If
End Function

--------------020702050705010702000306--
0
Reply QuoVadis 7/27/2006 3:00:26 PM


Hi,

On Thu, 27 Jul 2006 17:00:26 +0200 QuoVadis <nbs2000@directbox.com>
wrote:

> You can use Ghostscript to print PDF files from the command line.

Would have been my suggestion (or xpdf) if the OP has not said he was
searching for a free _and_ in the same moment commercially usable
software. Ghostscript is GPL/AFPL. Xpdf is GPL. So both require to
publish the source of a deriving application or to contact the devs for
an idividual licence, but that would probably not come for free.

Well, you could ignore Ghostscript's licence, like those cheap
Distiller substitutes. But that's not fair and one would deserve to get
sued for that.

OTOH, ghostscript could be included as-is, if that's possible. That
does not apply to embedding Ghostscript.

-hwh
0
Reply Hans 7/27/2006 3:16:54 PM

Hans-Werner Hilse wrote:
> Hi,
>
> On Thu, 27 Jul 2006 17:00:26 +0200 QuoVadis <nbs2000@directbox.com>
> wrote:
>
> > You can use Ghostscript to print PDF files from the command line.
>
> Would have been my suggestion (or xpdf) if the OP has not said he was
> searching for a free _and_ in the same moment commercially usable
> software. Ghostscript is GPL/AFPL. Xpdf is GPL. So both require to
> publish the source of a deriving application or to contact the devs for
> an idividual licence, but that would probably not come for free.
>
> Well, you could ignore Ghostscript's licence, like those cheap
> Distiller substitutes. But that's not fair and one would deserve to get
> sued for that.
>
> OTOH, ghostscript could be included as-is, if that's possible. That
> does not apply to embedding Ghostscript.
>
> -hwh

Then If I only use the GhostScript-API, not the Product GhostScript,
does it also has any commercial usage restriction?

0
Reply Audison 7/27/2006 4:24:09 PM

Audison.Athena@gmail.com wrote:


>Then If I only use the GhostScript-API, not the Product GhostScript,
>does it also has any commercial usage restriction?

An API to a product is a way of talking to the product.

For example, to use the Windows API, you must have Windows installed,
with whatever licensing issues it comes with.

Similarly, to use the GhostScript API, you must have GhostScript
installed, and its licensing terms apply.  

The GhostScript API is not a separate thing in itself.

It may be worth noting that printing a PDF is a vastly complex task,
representing perhaps 2-10 years of full time programming. Someone who
has gone to that trouble is likely to put at least some conditions on
reuse of their code.
----------------------------------------
Aandi Inston  quite@dial.pipex.com http://www.quite.com
Please support usenet! Post replies and follow-ups, don't e-mail them.

0
Reply quite 7/27/2006 5:01:53 PM

Hans-Werner Hilse schrieb:
 > Would have been my suggestion (or xpdf) if the OP has not said he was
 > searching for a free _and_ in the same moment commercially usable
 > software. Ghostscript is GPL/AFPL. Xpdf is GPL.

Calling GS from the command line rather than using the API is IMHO no violation of the GPL nor the AFPL, as you do do not alter the code of GS at all 
or do a static linking of the dll (but corrct me if I'm wrong).

 > OTOH, ghostscript could be included as-is, if that's possible. That
 > does not apply to embedding Ghostscript.

Making the user d/l and install GS shouldn't be a problem either.

Another option for your product could be a user-defined shell call using a placeholder like %1 for the PDF, so your end users can use any printing 
system that suites their needs (GS, Adobe Reader by cmdline or DDE).

Regards

Marcus


> Hi,
> 
> On Thu, 27 Jul 2006 17:00:26 +0200 QuoVadis <nbs2000@directbox.com>
> wrote:
> 
>> You can use Ghostscript to print PDF files from the command line.
> 
So both require to
> publish the source of a deriving application or to contact the devs for
> an idividual licence, but that would probably not come for free.
> 
> Well, you could ignore Ghostscript's licence, like those cheap
> Distiller substitutes. But that's not fair and one would deserve to get
> sued for that.
> 
0
Reply QuoVadis 7/27/2006 5:28:41 PM

QuoVadis wrote:

> ... Adobe Reader by cmdline or DDE

Such as pdfp here: http://www.esnips.com/web/PDFTools

Automating Reader is a very good way to print PDF with high quality, so
long as you realize the limitations.  Reader can't be fully automated,
since it displays error messages which must be responded to manually by
an operator.  Therefore it can't be automated as a Windows Service or
on a headless server.

0
Reply chicks 7/27/2006 5:44:22 PM

6 Replies
620 Views

(page loaded in 0.163 seconds)

Similiar Articles:













7/23/2012 7:08:50 PM


Reply: