25

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

yms
  • 10,361
  • 3
  • 38
  • 68
Mx.
  • 3,588
  • 2
  • 25
  • 33
  • try [Print existing PDF (or other files) in C#](http://stackoverflow.com/questions/273675/print-existing-pdf-or-other-files-in-c-sharp). – Rafal Jul 20 '12 at 13:14
  • To get Drawing.Image you can take a look at this sample: https://ghostscriptnet.codeplex.com/SourceControl/latest#Ghostscript.NET/Ghostscript.NET.Samples/Samples/RasterizerSample.cs – HABJAN Jan 17 '14 at 06:56
  • This is a couple of years later... have you been able to figure out the `Drawing.Image` route? – B.K. Nov 13 '14 at 17:22
  • @B.K. Sadly not - but may there is a better way today – Mx. Nov 13 '14 at 17:25
  • @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. – B.K. Nov 13 '14 at 19:34
  • Is there a solution on this. I am going through the exact same problem. Would appreciate if there is any recommendation – csensoft Jun 15 '15 at 18:52
  • 1
    @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. – Mx. Jun 15 '15 at 18:55
  • @Mx. alright. Thanks – csensoft Jun 15 '15 at 20:28

12 Answers12

8

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

  • 1
    I would recommend to use Ghostscript wrapper for this. Something like: http://ghostscriptnet.codeplex.com – HABJAN Oct 11 '13 at 15:33
  • @HABJAN Thanks for that suggestion, looks quite usable indeed. – Johan van der Slikke Oct 12 '13 at 20:25
  • 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 http://downloads.ghostscript.com/public/ – Keith Feb 01 '16 at 19:28
  • 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 http://effisoft.pl/rawfileprinter – zuko Jun 15 '16 at 07:58
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.
Ian
  • 841
  • 5
  • 10
  • After 6 years, I guess this is still the cleanest free solution to printing PDF files. It comes with a single portable exe file. No installation required. All you need to do is to copy this file into the folder where your exe file is. – Sinan ILYAS Feb 13 '23 at 13:11
  • I switched from Foxit PDF to Sumatra in 2015. Kind of depressing there are still no better options. – Ben Curthoys Jun 06 '23 at 16:10
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

yms
  • 10,361
  • 3
  • 38
  • 68
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.

Turbot
  • 5,095
  • 1
  • 22
  • 30
  • good point that i didn't mentioned in my answer. I'll update the answer, but might be what OP needed ? – Turbot Jul 20 '12 at 13:25
  • 1
    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. – Mx. Jul 20 '12 at 13:32
  • 1
    link now goes to a 404. – funkymushroom Oct 29 '19 at 16:49
  • revisit this, you probably can visit the raw print libraries written here. https://github.com/trehoffman/RawPrint with the implementation of Window Service, that probably can use `RawPrinterHelper.cs` – Turbot Jan 08 '23 at 14:54
1
Process proc = new Process();
proc.StartInfo.FileName = @"C:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe";
proc.StartInfo.Arguments = @"/p /h C:\Documents and Settings\brendal\Desktop\Test.pdf";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();

for (int i = 0; i < 5; i++)
{
    if (!proc.HasExited)
    {
        proc.Refresh();
        Thread.Sleep(2000);
    }
    else
        break;
}
if (!proc.HasExited)
{
    proc.CloseMainWindow();
}
jordanz
  • 367
  • 4
  • 12
Roshana
  • 428
  • 3
  • 15
1

My company offers Docotic.Pdf library that can render and print PDF documents. The article behind the link contains detailed information about the following topics:

  • printing PDFs in Windows Forms or WPF application directly
  • printing PDFs via an intermediate image
  • rendering PDFs on a Graphics

There are links to sample code, too.

I work for the company, so please read the article and try suggested solutions yourselves.

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
0

You can use ghostscript to convert PDF into image formats.

The following example converts a single PDF into a sequence of PNG-Files:

private static void ExecuteGhostscript(string input, string tempDirectory)
{
    // %d will be replaced by ghostscript with a number for each page
    string filename = Path.GetFileNameWithoutExtension(input) + "-%d.png";
    string output = Path.Combine(tempDirectory, filename);

    Process ghostscript = new Process();
    ghostscript.StartInfo.FileName = _pathToGhostscript;
    ghostscript.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

    ghostscript.StartInfo.Arguments = string.Format(
        "-dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r300 -sOutputFile=\"{0}\" \"{1}\"", output, input);

    ghostscript.Start();
    ghostscript.WaitForExit();
}

If you prefer to use Adobe Reader instead you can hide its window:

process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pescolino
  • 3,086
  • 2
  • 14
  • 24
0

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

Hinek
  • 9,519
  • 12
  • 52
  • 74
  • 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. – Hinek Sep 06 '12 at 08:05
0

If you're interested in commercial solutions which do exactly what you require then there are quite a few options. My company provides one of those options in a developer toolkit called Debenu Quick PDF Library.

Here is a code sample (key functions are PrintOptions and PrintDocument):

/* Print a document  */

// Load a local sample file from the input folder

DPL.LoadFromFile("Test.pdf", "");

// Configure print options

iPrintOptions = DPL.PrintOptions(0, 0, "Printing Sample")

// Print the current document to the default 
// printing using the options as configured above.
// You can also specify the specific printer.

DPL.PrintDocument(DPL.GetDefaultPrinterName(), 1, 1, iPrintOptions);
Rowan
  • 2,384
  • 2
  • 21
  • 22
0

I know that the tag has Windows Forms; however, due to the general title, some people might be wondering if they may use that namespace with a WPF application -- they may.

Here's code:

var file = File.ReadAllBytes(pdfFilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();

using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
{
    stream.Write(file, 0, file.Length);
}

Now, this namespace must be used with a WPF application. It does not play well with ASP.NET or Windows Service. It should not be used with Windows Forms, as it has System.Drawing.Printing. I don't have a single issue with my PDF printing using the above code.

Note that if your printer does not support Direct Printing for PDF files, this won't work.

B.K.
  • 9,982
  • 10
  • 73
  • 105
  • 1
    tried it. see it briefly populate in my printer queue before disappearing very quickly. Maybe my printer doesn't support it, but it does write to the queue! – Caleb W. Dec 05 '22 at 15:43
-1

What about using the PrintDocument class?

http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx

You just need to pass the filename of the file you want to print (based on the example).

HTH

Gavin
  • 6,284
  • 5
  • 30
  • 38
  • 2
    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. – Mx. Jul 20 '12 at 13:16
  • See http://www.daniweb.com/software-development/csharp/threads/90272/automatically-printing-pdf-from-c for a possible solution. – Gavin Jul 20 '12 at 13:20
-1

As of July 2018, there is still no answer for the OP. There is no free way to 1) silently print your pdf for a 2) closed source project.

1) You can most certainly use a process i.e. Adobe Acrobat or Foxit Reader

2) Free solutions have a GPL (GNU's General Public License). This means you must open your source code if giving the software, even for free, to anyone outside your company.

As the OP says, if you can get a PDF to Drawing.Image, you can print it with .NET methods. Sadly, software to do this also requires payment or a GPL.

John Doe
  • 165
  • 1
  • 4
  • 15