Silent printing PDF in .NET using gsprint and additional truetype fonts

30 04 2009

In my most recent project, one of the requirements of the applications, was to render reports using the SQL Report Services in a PDF format and print these PDF files to a network printer.
The PDF also contains a barcode section, as the printed reports will be processed by a sorting machine that automatically fills up envelopes with the reports, based on its barcode of course.

When looking into the options of printing a PDF file from .NET code, the only workable approaches where:
1) to use Adobe Acrobat Reader as a pipeline to open the file, and send it to the printer
2) using gsprint, a executable that comes with Ghostview (the GUI for GhostScript) and who’s able to send PS and PDF files to any printer that support printing PS/PDF files

At first, I tried the Adobe Reader way. This however, proved me quite some issues. For one, to be able to print using Adobe Reader, it needs an active window. So this result in having Adobe showing up in the foreground when printing files. Or even worse, flashing when printing multiple files in rapid succession, as Adobe keeps opening and closing every PDF file you send. So going this will not allow you the print files in a silent way.

The second drawback when using Adobe is the fact that when files need to be printed very quickly in a certain order, Adobe decides by itself the order of files it sends to the printer by creating his own queue (or so it looks like anyway). This results in a serie of files being printed in the wrong order allthough you have sent them in the right order to the Adobe process.

So, how about 3th party tools? Hmm, we weren’t exactly considering paying $1000 licenses in order to print a PDF file from .NET.
What about open-source libraries, like PDFSharp ? Well, I looked into them, and in the background all they do is approaching Adobe Reader as a process and perform the same actions as I described above, with the same disadvantages as result.

So, time to look for another solution!

After some more roaming on the internet, in search of a solution to my problem, I stumbled upon gsprint.exe, an executable under Free Public Licence, that comes with Ghostview
This is a GUI, running on GhostScript, an interpreter for the PostScript language and for PDF files.

Next, I’ll try to explain how to setup and use these tools to print from .NET.

Both programs can be download from the links provided in the section a couple of lines back. Download, and install those programs. I used the default locations in the installation procedure, so I’ll be using those locations through the rest of the post.

First thing, when using the latest versions of the applications, the documentation about the fonts has become obsolete. So adding additional fonts have to be done manually.

To be able to print our barcodes on the reports successfully, we needed the font installed and available for GhostView on the client pc.
As GhostView doesn’t automatically add any font available on the machine, we need to add it manually in its configuration.

I copied the TrueType font file to the C:\Program Files\gs\fonts directory. If the ‘fonts’ under your gs(GhostScript) folder does not exist, create it.

Then open up GhostView (you should have a GhostGum section added in Start – All Programs)

In GhostView, go to Options, and go for Advanced Configure…

GsView Advanced Options

Here you can configure some options GhostScript will work with.
As we want GhostScript to recognize our TrueType font, and replace it by one of its known fonts, we’ll add the location to our font:

GsView add font location

Ok, we have GhostScript/GhostView (and thus gsprint) set up. Now it’s time to do some simple coding making this stuff work…

Beware that gsprint should be approached through the commandline and will not automatically print the file in the correct orientation (portrait or landscape). The orientation however can be adjusted by calling the -landscape / -portrait option in the commandline. However, gsprint has no support for margin control, and will not automatically fit you PDF to your used paper size. So you should be sure those are set within you PDF file correctly.

Anyway, here’s my code I use to print my PDF files correctly:


public static void UseGSPrint(string PrinterName, string FileName, bool Portrait)
{
string gsArguments;
string gsLocation;
ProcessStartInfo gsProcessInfo;
Process gsProcess;
try
{
if (Portrait)
{
gsArguments = string.Format("-noquery -portrait -printer \"{0}\" \"{1}\"", PrinterName, FileName);
gsLocation = @"C:\Program Files\Ghostgum\gsview\gsprint.exe";
}
else
{
gsArguments = string.Format("-noquery -landscape -printer \"{0}\" \"{1}\"", PrinterName, FileName);
gsLocation = @"C:\Program Files\Ghostgum\gsview\gsprint.exe";
}
gsProcessInfo = new ProcessStartInfo();
gsProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
gsProcessInfo.FileName = gsLocation;
gsProcessInfo.Arguments = gsArguments;
gsProcess = Process.Start(gsProcessInfo);
gsProcess.WaitForExit();
EventsHelper.Fire(SentToPrinter);
}
catch (Exception ex)
{
ExceptionPolicy.HandleException(ex, "Client Policy");
}
}

As Tiago requested, I’ll add an example of calling the above method:

public void PrintTheFile()
{
String filename = @"C:\mytestfile.pdf";
String printername = @"\\MyHomeNetwork\HP3650";
UseGSPrint(printername, filename, true);
}

I hope this post has been somewhat usefull, as this was my first post covering a real .NET subject. It worked out quite well for me, as I no longer have annoying Adobe popups, and can rest asure my print order will be kept the way I send it down the pipeline…


Actions

Information

18 responses

24 06 2009
dia

excellent article! I’ve been struggling with acrobat and troubleshooting for days why documents don’t print in the right order. This worked great!
thanks

25 06 2009
woal

No problem, glad I could help out with this article 🙂

24 07 2009
Tiago

Can you past an example using UseGSPrint routine?
Thx

6 08 2009
woal

Ok, I’ll update the article with an example asap.

I also redesigned this part of my code for later re-use, and I hope I’ll find the time tomorrow to write an article about it and posting the code.

24 07 2009
Tiago

Can you past an example using de UseGSPrint routine?
Thank you

5 10 2009
Srinivasa

Hi

May i know about EventsHelper.Fire(SentToPrinter);

how to use this silent printing in windows Service.

Regards

15 10 2009
woal

Hi there,

The EventsHelper.Fire(SentToPrinter) is just a call of a statis method that handles treadsafe events. If I’m not mistaken, it’s included in the Microsoft Entreprise Library. Anyway, the event does nothing but throwing a notice to the calling class that the files are sent to the printer, so I could update a status on the client view…
If you want to use it in a webservice, you just need to call the function to send the files to the printer, and then it is up to you whether or not to throw an event after it’s sent to the printer…

I’ve been very busy lately (actually I still am) with the construction of our house, but I wrote a small ‘library’ for printing to PDF with more options then in the current article. If I find some time, I’ll try to put it down in an article…

14 10 2009
Alice

Hello, just wondering if this will do the following things:
1. Change Paper size
2. Print double sided

Also, if I am reading correctly, this method will only work if your client also has gsprint installed?

Thank you.

15 10 2009
woal

Hi Alice,

The function described in the article does allow you to print double sided or not (that’s the duplex option), but doesn’t let you change paper size yet. I should look into the gsprint properties to check if that option is supported.
As written on my previous comment on Srinivasa’s post, I hope to find some time soon to write the article about a small library I wrote to manage printing to PDF (extendible for other output) with more options available then in the function in this article.

Assuming that the method that calls the print function is launched from a client perspective, then yes, gsprint should be installed on the client as well. But if you delegate the print function to a server side component with access to the (network)printer, then it’s only required to be installed on the server.
I haven’t tried to install gsprint on a networklocation yet, but then you’re creating new security concerns with users needing privileges to run a remote executable.

These are just some options I’m throwing, in the end it is a consideration the developer should make to do clientside printing, serverside, or perhaps trying running gsprint over a networklocation…

11 11 2009
Frank Qian

Excellent! I will try your method later.

We achieved the silent printing to avoid pdf popups only works under Adobe reader (7.1 version NOT 7.0). We had no problem until we recently trying to upgrade all of our Window Xp to 7.0. It complain Adobe 7 is not compatible to Window 7. So it’s time to try your method. Thanks for your great article.

11 01 2010
Joe

Hi.
I’m using gsprint but I have this issue:
if I don’t know if a PDF file is landscape or portrait, how can I write it correctly?
There is an option like AutoSize?

Thank you in advance

6 10 2010
G SlickDawg

Damn, this actually works like a charm!!!

Thank you Jesus, and thank you Mr woal; you have NO IDEA how many Forums/Blogs I’ve Googled until I stumbled across this.

Btw, if you do manage to change the paper size programatically, please keep us posted. Tnx again, man!

13 03 2011
Andrew

Thanks for the article. I appreciate the well explained path of different options you have tried and the code for this solution worked perfectly. Do you know if I address a printer with an IP Address or just with the printer name as shown here?

6 02 2012
Stu

Wow. Thanks very much for the succinct, easy code. Saved the day for me.

17 10 2012
codewhisperer

AMEN BRO!!!!! YOU ARE A LIVE SAVER!!!!

28 12 2012
Dan Williams

Have you had any problems getting this to work on a Windows 2008 server with IIS 7? I’m moving my web app to a newserver and can’t get this to work now. It seems to work ok when i run it from a command prompt, but when running it within my code, i get “Couldn’t open Windows GDI printer driver”.

It’s like my ProcessInfo Arguments aren’t getting accepted. I even get the following error output which shows the Requested Printer as being one of the available printers!!

Error sending files to printer. ExitCode: 1

StandardOutput: Copyright (C) 2003-2006, Ghostgum Software Pty Ltd. All Rights Reserved. 2006-02-24 gsprint 1.9

StandardError: Couldn’t open Windows GDI printer driver Requested printer: “Byre Printer” Available printers: “Microsoft XPS Document Writer” “HeadOffice” “Byre Printer”

7 11 2015
Abhishek Tandon

Hello
This is an excellent article you have pasted here which ended my year long search for a faster method of printing bulk PDF files.
However I am still facing one issue. The printed Output is displaying some straight light grey lines in almost all the pages and in different places. These lines are not there in the original PDF file and also If I print the file through Acrobat Reader these lines are not displayed.
Can you tell me possible reason why these are coming? Kindly let me know if this can be resolved
Thanks in Advance

25 11 2015
Wim Naessens

Hey thanks Wouter, even so much years later there’s people being helped by this. Would have been nice I’ve you’d included with libraries you imported. The Processinfo class is found easily enough, but we were unable to find the Eventhelper thing (the code works without it so we cut it out).

Leave a reply to woal Cancel reply