views:

4657

answers:

22

It's the "printing question guy" again. Looking for a third-party solution to print PDFs, preferable from a service. I have seen some arguments against it, but due to our use case, this really is the preferred solution - the service will be receiving messages from a messaging bus, and there shouldn't be any sort of delay between the receipt of that message and the printing of the report. So far, I've found 1 solution from PDF Tools that seems very nice, and very flexible. The problem is that it's licensed per server. If anyone knows of any third-party solutions that have a seat license (per developer, unlimited runtime distribution), that would be much preferred.

EDIT: Clarification, by printing, I mean sending the PDF to a printer.

+2  A: 

ITextSharp used to be a good choice, and it's free (LGPL). It doesn't seem to have been updated for a while, so it might be a PITA to get it working right.

deadtime
ITextSharp does not seem to have any Printer functionality that I can find
Chris Marasti-Georg
+2  A: 

I'm not sure if this is quite what you want, but the way I've done similar before is to use foxit reader as a commandline app with the /p parameter to print - e.g.

'C:\Program Files\Foxit Software\Foxit Reader\Foxit Reader.exe' /p C:\path\to\file.pdf

Whisk
This looks like it could be workable - they also have an SDK available with custom licensing
Chris Marasti-Georg
+5  A: 

I've just used iTextSharp on a project at work and it proved to be very easy to use, and it's completely free. I got it working in about 30 minutes from download to first test. Printing a block of text without formatting only took the code below to work. This was for a user clicking a link and getting the service agreement text, which was dynamically generated, and then sending it to the user to download.

The website has examples on doing more complicated formatting, as well, and it all looked fairly rational. I'd give it a try, at least, to see if it does what you need.

// Create the iText PDF document and the memory stream we'll send to the user
Document pdfDoc = new Document();
MemoryStream stream = new MemoryStream();
PdfWriter.GetInstance(pdfDoc, stream);
//Open the PDF document and add the AgreementBox text to it
pdfDoc.Open();
pdfDoc.Add(new Paragraph(GetAgreement()));
pdfDoc.Close();
// Send the memory stream to the user as an attachment.
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=agreement.pdf");
Response.OutputStream.Write(stream.GetBuffer(), 0, stream.GetBuffer().Length);
Response.OutputStream.Flush();
Response.OutputStream.Close();

Eric Sipple

saalon
ITextSharp does not seem to have any Printer functionality that I can find
Chris Marasti-Georg
A: 

PDFSharp is your friend here. These guys provide a nice set of OS libraries that I have used for PDF jiggery-pokery before.

You'll probably want the PdfSharp.Pdf.Printing.PdfFilePrinter class.

Just load up your pdf and call print()... nice and easy.

John Nolan
PDFSharp seems to just call acrobat reader, which does not support silent command line printer invocation.
Chris Marasti-Georg
+1  A: 

@John Nolan - PDFSharp seems to just call acrobat reader, which does not support silent command line printer invocation. From Reflector:

public void Print(int milliseconds)
{
    if ((this.printerName == null) || (this.printerName.Length == 0))
    {
        this.printerName = defaultPrinterName;
    }
    if ((adobeReaderPath == null) || (adobeReaderPath.Length == 0))
    {
        throw new InvalidOperationException("No full qualified path to AcroRd32.exe or Acrobat.exe is set.");
    }
    if ((this.printerName == null) || (this.printerName.Length == 0))
    {
        throw new InvalidOperationException("No printer name set.");
    }
    string path = string.Empty;
    if ((this.workingDirectory != null) && (this.workingDirectory.Length != 0))
    {
        path = Path.Combine(this.workingDirectory, this.pdfFileName);
    }
    else
    {
        path = Path.Combine(Directory.GetCurrentDirectory(), this.pdfFileName);
    }
    if (!File.Exists(path))
    {
        throw new InvalidOperationException(string.Format("The file {0} does not exists.", path));
    }
    try
    {
        this.DoSomeVeryDirtyHacksToMakeItWork();
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.FileName = adobeReaderPath;
        string str2 = string.Format("/t \"{0}\" \"{1}\"", this.pdfFileName, this.printerName);
        startInfo.Arguments = str2;
        startInfo.CreateNoWindow = true;
        startInfo.ErrorDialog = false;
        startInfo.UseShellExecute = false;
        if ((this.workingDirectory != null) && (this.workingDirectory.Length != 0))
        {
            startInfo.WorkingDirectory = this.workingDirectory;
        }
        Process process = Process.Start(startInfo);
        if (!process.WaitForExit(milliseconds))
        {
            process.Kill();
        }
    }
    catch (Exception exception)
    {
        throw exception;
    }
}
Chris Marasti-Georg
"DoSomeVeryDirtyHacksToMakeItWork( )" what a nice Function name... I loved it!!
Romias
+1  A: 

@Chris Marasti-Georg Looking into it further, I see what you mean. I thought I had seen printer functionality when I was using this for my web solution, but it appears I simply fantasized that :/.

iText is great to generate the PDF should you need to dynamically generate it before printing, but you'd probably need to save said pdf and then call another application like Foxit as Whisk suggested, or use Ghostwriter as I read online during my research.

My apologies for my poor memory on this one.

-Eric Sipple

saalon
+1  A: 

If we end up going with this solution, VeryPDF's PDFPrint looks like the tool we'll use. Thanks for the help all.

Chris Marasti-Georg
+1  A: 

I been using ABC PDF for convert html to PDF, but I think the redistribution license is very expensive ($4790 USD, we use the professional license), it works just fine.

Also I found this article in code project, who implements a windows service, .Net remoting and open office in a service-oriented architecture.

http://www.codeproject.com/KB/files/generatepdf.aspx

jl23x
A: 

check out the report viewer control. It can render as PDF.
http://www.gotreportviewer.com/

Q: Does PDF export require an Adobe license?

A: No. The ReportViewer control does not use any Adobe code to generate PDF files. PDF is an open format, and anyone can create PDF files without requiring a special license. Q: What are the limitations of ReportViewer control?

A: Unlike the Report Server the ReportViewer control does not connect to databases or execute queries. Also, in local mode the only export formats available are Excel and PDF. (In remote mode all formats supported by the Report Server are available.) The ReportViewer control cannot be extended by adding custom renderers or custom report items.

Besides additional export formats, the Report Server offers better scalability, central storage, management and access control of reports, caching, subscriptions, etc.

jms
+2  A: 

I have used the free (AFPL and GPL) Ghostscript to print Postscript and PDF from un*x. You can pipe the pdf data to a command line version and then print using lp, where you'd specify the printer name on the server.

On windows it is very similar;

set PATH=%PATH%;C:\Program Files\gs\gs8.51\bin
gswin32c -sDEVICE=mswinpr2 -sPAPERSIZE=a4 -sOutputFile="\\spool\PERTH" -dNOPAUSE -dNoCancel -dBATCH testpdf2.pdf -c quit

Replace PERTH with your windows printer name, and testpdf2.pdf with your pdf file. Also note that in version 8.51 i tried piping the data to gswin32c, but it crashed regularly with postscript files, so i stick with writing a file, then reading a file. This may be fixed in more recent releases.

To implement this on ASP.net you could set up some sort of on demand calling of this (not recommended as it is slowish) or a batch polling job, or even a service.

NB: You had another question on printing HTML. If you could convert your HTML to PS or PDF then you job could be completed with Ghostscript. I have used HTMLDOC to do something similar.

NB: The GPL version should allow commercial distribution of the Ghostscript application as long as you distribute the source code. It's a different matter if you copy parts of the source code and use it. Please read the GPL license though and check for yourself.

Mark Nold
A: 

I looked into this actually, and unfortunately, ghostscript is not free for commercial use. I didn't get a chance to look into the actual cost of licensing, but it did not seem insignificant.

Chris Marasti-Georg
A: 

I started using the free community edition from dynamicpdf.com it works very well and you can upgrade later to get the full feature set if needed.

Brian Boatright
A: 

How about PDF Rasterizer.NET from Tall components? I've used Tall's other PDF components before and they were pretty good. I don't have any experience of Rasterizer, but the samples seem to indicate that it's an expected use-case.

In terms of licensing, it's on the expensive side but you can have a "Server" licence or a "Client Application" license.

Martin Clarke
+1  A: 

i use pdftops.exe from here:

http://www.foolabs.com/xpdf/download.html

i convert the pdf file to postscript by kicking off and wating for it to process

I then read in the entire ps file into a string and print it using a RawPrinter:

Imports System.Runtime.InteropServices

Public Class RawPrinter Private _printerFound As Boolean Private _printerPrinted As Boolean Private _docName As String

' ----- Define the data type that supplies basic
'       print job information to the spooler.
<StructLayout(LayoutKind.Sequential, _
    CharSet:=CharSet.Unicode)> _
Public Structure DOCINFO
    <MarshalAs(UnmanagedType.LPWStr)> _
       Public pDocName As String
    <MarshalAs(UnmanagedType.LPWStr)> _
       Public pOutputFile As String
    <MarshalAs(UnmanagedType.LPWStr)> _
       Public pDataType As String
End Structure

' ----- Define interfaces to the functions supplied
'       in the DLL.
<DllImport("winspool.drv", EntryPoint:="OpenPrinterW", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function OpenPrinter( _
   ByVal printerName As String, ByRef hPrinter As IntPtr, _
   ByVal printerDefaults As Integer) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="ClosePrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function ClosePrinter( _
   ByVal hPrinter As IntPtr) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="StartDocPrinterW", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function StartDocPrinter( _
   ByVal hPrinter As IntPtr, ByVal level As Integer, _
   ByRef documentInfo As DOCINFO) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="EndDocPrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function EndDocPrinter( _
   ByVal hPrinter As IntPtr) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="StartPagePrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function StartPagePrinter( _
   ByVal hPrinter As IntPtr) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="EndPagePrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function EndPagePrinter( _
   ByVal hPrinter As IntPtr) As Boolean
End Function

<DllImport("winspool.drv", EntryPoint:="WritePrinter", _
   SetLastError:=True, CharSet:=CharSet.Unicode, _
   ExactSpelling:=True, _
   CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function WritePrinter( _
   ByVal hPrinter As IntPtr, ByVal buffer As IntPtr, _
   ByVal bufferLength As Integer, _
   ByRef bytesWritten As Integer) As Boolean
End Function

Public Sub New()
    _printerFound = False
    _printerPrinted = False

End Sub

Public Function PrintRaw( _
      ByVal printerName As String, _
      ByVal origString As String) As Boolean
    ' ----- Send a string of raw data to the printer.
    Dim hPrinter As IntPtr
    Dim spoolData As New DOCINFO
    Dim dataToSend As IntPtr
    Dim dataSize As Integer
    Dim bytesWritten As Integer

    ' ----- The internal format of a .NET String is just
    '       different enough from what the printer expects
    '       that there will be a problem if we send it
    '       directly. Convert it to ANSI format before
    '       sending.
    dataSize = origString.Length()
    dataToSend = Marshal.StringToCoTaskMemAnsi(origString)

    ' ----- Prepare information for the spooler.
    spoolData.pDocName = _docName
    spoolData.pDataType = "RAW"

    Try
        ' ----- Open a channel to the printer or spooler.
        Call OpenPrinter(printerName, hPrinter, 0)

        If hPrinter <> 0 Then
            _printerFound = True
            ' ----- Start a new document and page 1.
            Call StartDocPrinter(hPrinter, 1, spoolData)
            Call StartPagePrinter(hPrinter)

            ' ----- Send the data to the printer.
            Call WritePrinter(hPrinter, dataToSend, dataSize, bytesWritten)

            If dataSize = bytesWritten Then
                _printerPrinted = True
            End If
            ' ----- Close everything that we opened.
            EndPagePrinter(hPrinter)
            EndDocPrinter(hPrinter)
            ClosePrinter(hPrinter)
        End If

    Catch ex As Exception
        'MsgBox("Error occurred: " & ex.ToString)
    Finally
        ' ----- Get rid of the special ANSI version.
        Marshal.FreeCoTaskMem(dataToSend)
    End Try
End Function

Public Property PrinterFound() As Boolean
    Get
        Return _printerFound
    End Get
    Set(ByVal value As Boolean)
        _printerFound = value
    End Set
End Property

Public Property PrinterPrinted() As Boolean
    Get
        Return _printerPrinted
    End Get
    Set(ByVal value As Boolean)
        _printerPrinted = value
    End Set
End Property

Public Property DocName() As String
    Get
        Return _docName
    End Get
    Set(ByVal value As String)
        _docName = value
    End Set
End Property

End Class

quimbo
A: 

I use and like the DynamicPDF products from ceTe. They are a bit pricey but there is a lot of functionality in the product suite.

Mark Brittingham
A: 

My company sells a PDF rasterizer and an associated set of image manipulation tools. Printing a PDF is straight forward.

plinth
A: 

We used PDF Xchange (http://www.docu-track.com/). They have the PDF-XChange Driver's API SDK (about $840), which allows you to interact with the print driver. It also includes their API viewer SDK with which you can print PDF files and bypass Adobe Reader.

A year had passed since you started this thread - did you find a solution?

idophir
A: 

For a free solution you can look into these java libraries and run them either in IKVM or write a small Java wrapper around them. You can, for example create an application that just reads a base64-encoded document from stdin, renders it and writes the result base64-encoded to stdout.

erikkallen
A: 

Tested w/Reader v9.

            string myargs = "/s /o /h /p" + @"c:\something.pdf";

            System.Diagnostics.Process p = new System.Diagnostics.Process();

            p.StartInfo.FileName = "AcroRd32.exe";
            p.StartInfo.Arguments = myargs;
            p.StartInfo.UseShellExecute = true;
            p.Start();
Tori Marrama
process object won't let you printting in slient mode and makes you a lot of problems since you want bulk printing.
austin powers
+1  A: 

I used: http://www.pdftron.com/pdfnet/samplecode.html#PDFPrint

Lary
+2  A: 

PDFRasterizer from Tall Components does exactly what you need: it rasterizes (ie converts into printable form) individual pages from a PDF. It's very easy to build on that to create a print job for a whole document.

It's a fully-.NET product, and works well in server environments. It's very well made. (I have no affiliation with them, I'm just a satisfied customer).

The only downside is that it is quite expensive. But as you've probably noticed, there just aren't a lot of products that can reliably print PDFs from inside a server.

Paul Lalonde
A: 

EzPDFlibrary can printing PDF files easily.

Sarah