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…