How to print a PDF with C#

80,778

Solution 1

The most flexible, easiest and best performing method I could find was using GhostScript. It can print to windows printers directly by printer name.

"C:\Program Files\gs\gs9.07\bin\gswin64c.exe" -dPrinted -dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -dNoCancel -sOutputFile="%printer%printer name" "pdfdocument.pdf"

Add these switches to shrink the document to an A4 page.

-sPAPERSIZE=a4 -dPDFFitPage

Solution 2

Another approach would to use spooler function in .NET to send the pre-formatted printer data to a printer. But unfortunately you need to work with win32 spooler API

you can look at How to send raw data to a printer by using Visual C# .NET

you only can use this approach when the printer support PDF document natively.

Solution 3

If a commercial library is an option, you can try with Amyuni PDF Creator. Net.

Printing directly with the library:
For opening a PDF file and send it to print directly you can use the method IacDocument.Print. The code in C# will look like this:

// Open PDF document from file<br>
FileStream file1 = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc1 = new IacDocument (null);
doc1.Open (file1, "" );
// print document to a specified printer with no prompt
doc1.Print ("My Laser Printer", false);

Exporting to images (then printing if needed):
Choice 1: You can use the method IacDocument.ExportToJPeg for converting all pages in a PDF to JPG images that you can print or display using Drawing.Image

Choice 2: You can draw each page into a bitmap using the method IacDocument.DrawCurrentPage with the method System.Drawing.Graphics.FromImage. The code in C# should look like this:

FileStream myFile = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc = new IacDocument(null);
doc.Open(myFile);
doc.CurrentPage = 1;
Image img = new Bitmap(100,100);
Graphics gph = Graphics.FromImage(img);
IntPtr hdc = gph.GetHDC();
doc.DrawCurrentPage(hdc, false);
gph.ReleaseHdc( hdc );

Disclaimer: I work for Amyuni Technologies

Solution 4

I tried many things and the one that worked best for me was launching a SumatraPDF from the command line:

// Launch SumatraPDF Reader to print
String arguments = "-print-to-default -silent \"" + fileName + "\"";
System.Diagnostics.Process.Start("SumatraPDF.exe", arguments);

There are so many advantages to this:

  1. SumatraPDF is much much faster than Adobe Acrobat Reader.
  2. The UI doesn't load. It just prints.
  3. You can use SumatraPDF as a standalone application so you can include it with your application so you can use your own pa. Note that I did not read the license agreement; you should probably check it out yourself.

Solution 5

I found a slightly different version of your code that uses the printto verb. I didn't try it, but maybe it helps you:

http://vbcity.com/forums/t/149141.aspx

Share:
80,778

Related videos on Youtube

Mx.
Author by

Mx.

Updated on March 24, 2021

Comments

  • Mx.
    Mx. about 3 years

    I´ve trying to solve this problem for nearly 2 days. There are a lot of more or fewer good solutions on the net, but not a single one fits my task perfectly.

    Task:

    • Print a PDF programmatically
    • Do it with a fixed printer
    • Don´t let the user do more than one Button_Click
    • Do it silent - the more, the better
    • Do it client side

    First Solutions:

    Do it with a Forms.WebBrowser

    If we have Adobe Reader installed, there is a plugin to show PDF´s in the webbrowser. With this solution we have a nice preview and with webbrowserControlName.Print() we can trigger the control to print its content.

    Problem - we still have a PrintDialog.


    Start the AcroRd32.exe with start arguments

    The following CMD command let us use Adobe Reader to print our PDF.

    InsertPathTo..\AcroRd32.exe /t "C:\sample.pdf" "\printerNetwork\printerName"

    Problems - we need the absolute path to AcroRd32.exe | there is an Adobe Reader Window opening and it has to be opened until the print task is ready.


    Use windows presets

    Process process = new Process();
    
    process.StartInfo.FileName = pathToPdf; 
    process.StartInfo.Verb = "printto";
    process.StartInfo.Arguments = "\"" + printerName + "\""; 
    process.Start();
    
    process.WaitForInputIdle();
    process.Kill();
    

    Problem - there is still an Adobe Reader window popping up, but after the printing is done it closes itself usually.

    Solution - convince the client to use Foxit Reader (don´t use last two lines of code).


    Convert PDF pages to Drawing.Image

    I´ve no idea how to do it with code, but when I get this to work the rest is just a piece of cake. Printing.PrintDocument can fulfill all demands.


    Anyone an idea to get some Drawing.Image´s out of those PDF´s or another approach how to do it?

    Best Regards, Max

    • Rafal
      Rafal almost 12 years
    • HABJAN
      HABJAN over 10 years
      To get Drawing.Image you can take a look at this sample: ghostscriptnet.codeplex.com/SourceControl/…
    • B.K.
      B.K. over 9 years
      This is a couple of years later... have you been able to figure out the Drawing.Image route?
    • Mx.
      Mx. over 9 years
      @B.K. Sadly not - but may there is a better way today
    • B.K.
      B.K. over 9 years
      @Max I've been looking around for several months and I've yet to find a solution that doesn't involve installing something on the client machine... which is not an option in my case.
    • csensoft
      csensoft almost 9 years
      Is there a solution on this. I am going through the exact same problem. Would appreciate if there is any recommendation
    • Mx.
      Mx. almost 9 years
      @csensoft Still nothing that matches this specific requirement. I went with adding an extra service that would handle the Printing. Here are a lot of good answers that may help you.
    • csensoft
      csensoft almost 9 years
      @Mx. alright. Thanks
  • Mx.
    Mx. almost 12 years
    As I described, this would work with a Drawing.Image for example. It won´t work with a .pdf. Check up the pd_PrintPage(object sender, PrintPageEventArgs ev) Event. There is every line in the .txt file converted for the print output.
  • Gavin
    Gavin almost 12 years
  • Turbot
    Turbot almost 12 years
    good point that i didn't mentioned in my answer. I'll update the answer, but might be what OP needed ?
  • Mx.
    Mx. almost 12 years
    Good point, but I can´t be sure that all printers support it natively. Even if at the moment all printers support it, there would be a problem if they will buy another product without this feature.
  • Hinek
    Hinek over 11 years
    Ok, just saw this won't work: Adobe's forum says, new versions of Adobe Reader will not allow you to print "silent", "for security reasons" (sure, Adobe) ... there will always be a window.
  • HABJAN
    HABJAN over 10 years
    I would recommend to use Ghostscript wrapper for this. Something like: ghostscriptnet.codeplex.com
  • Johan van der Slikke
    Johan van der Slikke over 10 years
    @HABJAN Thanks for that suggestion, looks quite usable indeed.
  • Keith
    Keith over 8 years
    I used Ghostscript.NET (available via NuGet). When I tried the latest version of ghostscript (9.18), I received memory access exceptions. I uninstalled 9.18, and found that the latest version prior to the last build of Ghostscript.NET was 9.15. Once I installed that, everything appears to have started working. You can get prior releases of ghostscript at downloads.ghostscript.com/public
  • zuko
    zuko almost 8 years
    Ghostscript's mswinpr2 quality is rather poor - it converts input PDF file to raster file and prints it. The better approach is to use 3rd party component or try to implement something on your own, especially PDF/PS are well known by printers. Here I found simple and nice command line tool effisoft.pl/rawfileprinter
  • funkymushroom
    funkymushroom over 4 years
    link now goes to a 404.