5

I am in need of your support on the following issue since its pulling me for a while. We have a small c# utility, which print given PDF using GhostScript. This print as expected but fail to retain the page formatting’s. However, pages are printed as expected when I switch Adobe Acrobat in place of GhostScript. So I presume, I am making some obvious mistake on the GhostScript's command line arguments .

Background

Following is the core c# logic, which print a given PDF file with varying style across each pages. The given PDF file has pages;

  1. with inconsistent font style and colour
  2. some of the pages have normal font size where others are printed in extra small
  3. some of the pages has recommended margin but others have very small margin
  4. some of the pages are in colour and the rest in grey.
  5. some of the pages are landscape in style where other are portrait

In concise, the PDF which I am trying to print is nothing but a consolidation (joining individual pdfs into one large pdf) of numerous small sized pdf document with varying fonts style, size, margins.

Issue

Following logic use GhostScript(v9.02) to print PDF file. Though the following logic print any given PDF, it fail to retain the page formatting including header, footer, font size, margin, orientation ( my pdf file has pages those both landscape and portrait).

Interestingly, if I use acrobat reader to print the same PDF then it will print as expected along with all page level formatting's.

PDF specimen: First section, Second section

  void PrintDocument()
    {
         var psInfo = new ProcessStartInfo();
                psInfo.Arguments =
                    String.Format(
                        " -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=ljet4 -sOutputFile=\"\\\\spool\\{0}\" \"{1}\"",
                        GetDefaultPrinter(), @"C:\PDFOutput\test.pdf");
                psInfo.FileName = @"C:\Program Files\gs\gs9.10\bin\gswin64c.exe";
                psInfo.UseShellExecute = false;

        using (var process= Process.Start(psInfo))
        {
            process.WaitForExit();
        }
    }
S.N
  • 4,910
  • 5
  • 31
  • 51
  • Just to make sure i understood your issue: Is your problem related to merging PDF files (and not actually creating or really printing PDFs)? –  Dec 11 '13 at 16:27
  • @elgonzo, The issue is to do with Printing and not merging. – S.N Dec 11 '13 at 16:29
  • Now i am confused... Why are you talking about Acrobat and about joining individual PDFs into one larger PDF, if it is only about printing and not merging PDFs? –  Dec 11 '13 at 16:30
  • From our project's experience, GhostScript/GhostPDL (PCL)/GhostXPS are actually very inconsistent with font support, neither should be used in production cycle unless it's a core of ghost-oriented DTP. – kagali-san Dec 11 '13 at 17:16
  • Perhaps you should report the problems so they get fixed. As far as I am aware Ghostscript fully supports all font types. Of course, if you don't embed or supply the fonts then you will get substitutes, but that's not the application's fault. – KenS Dec 12 '13 at 12:01
  • @KenS, When i compare the print out from Adobe and GhostScript, the only difference is in font size. This means both are printing using same font but ghost print slightly bigger than adobe and hence i have one line cut of. Meantime, do you know anything about controlling font size ? – S.N Dec 12 '13 at 12:18
  • @KenS, Thank you for the consistent support. Now I am moving to a direction where I can find the fontmap file and see how to map fonts in it. – S.N Dec 12 '13 at 12:27
  • The text isn't written line by line as it is in a text file, it is positioned on the page, so the size of the font makes no difference. If the font is larger than expected then glyphs will collide, but the text position will still be OK. I can't see how the font could make a difference to this. What might make a difference is the media size,very possibly you have Acrobat's print dialog set to 'shrink to fit' or something similar which is reducing the actual page size so that it fits onto the printed page (taking margins into account). I am unsure if the mswinpr2 device offers this. – KenS Dec 12 '13 at 13:01
  • @KenS, I did tried to print the document through GSview UI (while completely avoiding my c# code which call GhostScript) and enabled mswinpr2 as print method. Also set 'Shrink to fit Page Size'. Still no luck with it. Do you know any other pdf printing software exluding Adobe ? – S.N Dec 12 '13 at 13:17
  • I suspect that gsview/gsprint is not setting the scaling appropriately to take into account margins, from your description. I don't know of anything else under Windows which will print to an arbitrary printer, but its likely there are other possible solutions. Perhaps you could install CUPS in some way. – KenS Dec 12 '13 at 17:07
  • @KenS, I was able to get it printed the way I wanted using GSView with GhostScript. But, now it's not printed as grey though I mentioned color and printed as single page though it is defined as duplex. I checked my default printer to verified whether it is on color and support duplex. – S.N Dec 12 '13 at 17:52
  • @KenS, Following is what I am doing and is printed as expected.-dPDFSETTINGS=/default -dAutoRotatePages=/PageByPage -dEmbedAllFonts=true -dSubsetFonts=true -sPAPERSIZE=a4 -dFIXEDMEDIA -dPDFFitPage -dBATCH -dNOPROMPT -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -noquery -all -colour -sDEVICE=mswinpr2 -sOutputFile="\\spool\\\Xerox Phaser 7500DT1" "C:\PRINTFOLDER\AppFormTLE.pdf" . Still trying to figureout why it is not printed in color and duplex. Thanks for your support. – S.N Dec 12 '13 at 18:06
  • You might want to put the solution in an answer below. That will keep things cleaner and easier to vote for. – Emond Dec 16 '13 at 11:35

4 Answers4

3

Answer - UPDATE 16/12/2013

I was managed to get it fixed and wanted to enclose the working solution if it help others. Special thanks to 'KenS' since he spent lot of time to guide me.

To summarize, I finally decided to use GSView along with GhostScript to print PDF to bypass Adobe. The core logic is given below;

 //PrintParamter is a custom data structure to capture file related info
private void PrintDocument(PrintParamter fs, string printerName = null)
        {
            if (!File.Exists(fs.FullyQualifiedName)) return;

            var filename = fs.FullyQualifiedName ?? string.Empty;
            printerName = printerName ?? GetDefaultPrinter(); //get your printer here

            var processArgs = string.Format("-dAutoRotatePages=/All -dNOPAUSE -dBATCH -sPAPERSIZE=a4 -dFIXEDMEDIA -dPDFFitPage -dEmbedAllFonts=true -dSubsetFonts=true -dPDFSETTINGS=/prepress -dNOPLATFONTS -sFONTPATH=\"C:\\Program Files\\gs\\gs9.10\\fonts\" -noquery -dNumCopies=1 -all -colour -printer \"{0}\" \"{1}\"", printerName, filename);
            try
            {

                var gsProcessInfo = new ProcessStartInfo
                                        {
                                            WindowStyle = ProcessWindowStyle.Hidden,
                                            FileName = gsViewEXEInstallationLocation,
                                            Arguments = processArgs
                                        };
                using (var gsProcess = Process.Start(gsProcessInfo))
                {

                    gsProcess.WaitForExit();

                }

        }
S.N
  • 4,910
  • 5
  • 31
  • 51
2

I think you asked this question before, and its also quite clear from your code sample that you are using GSView, not Ghostscript.

Now, while GSView does use Ghostscript to do the heavy lifting, its a concern that you are unable to differentiate between these two applications.

You still haven't provided an example PDF file to look at, nor a command line, though you have now at least managed to quote the Ghostscript version. You need to also give a command line (no I'm not prepared to assemble it from reading your code) and you should try this from the command line, not inside your own application, in order to show that its not your application making the error.

You should consider upgrading Ghostscript to the current version.

Note that a quick perusal of your code indicates that you are specifying a number of command line options (eg -dPDFSETTINGS) which are only appropriate for converting a file into PDF, not for any other purpose (such as printing).

So as I said before, provide a specimen file to reproduce the problem, and a command line (preferably a Ghostscript command line) which causes the problem. Knowing which printer you are using would probably be useful too, although its highly unlikely I will have a duplicate to test on.

KenS
  • 30,202
  • 3
  • 34
  • 51
  • Thanks for your response. (1) After goggling, my impression was that GsView uses GhostScript to print PDF. I think i need review my understanding. (2) Would you be able to help me or direct me on how to use GhostScript to print PDF without GSView ? (3) When it comes to sample PDF, I can assure you one thing that the document contains NDA's and financial information's and hence I can't share it. Sorry about that. But definitely, I will look for some obsolete/old PDF files(4) You are absolutely right and I was trying with random command line option due lack of knowledge. – S.N Dec 11 '13 at 16:45
  • As per your advise, I modified my initial post and my application, which replace use of GSView and now it completely rely on GhostScript. However, the issue continue to hold good. Any helps?? – S.N Dec 11 '13 at 17:15
  • GSView does use Ghostscript, but the command line parameters are not the same. If you can't share a document which causes a problem there is nothing further I can do to help. Perhaps you can create one which you can share. To print a file (under Windows) using Ghostscript you need to use the mswinpr2 device. – KenS Dec 11 '13 at 19:16
  • I attached the specimen of the documents. In reality we join these documents (on after the other) before printing. But this joining process is been done by third-party hence I have no control over it. However, these individual documents are good enough to reproduce the issue. Also, as you suggested, I am open to use either GhostScript or GSView with GhostScript to print the documents. – S.N Dec 12 '13 at 08:40
  • Well app1.pdf is broken, it contains 2 %%EOF and 2 startxref directives (there should only be 1). Ghostscript repairs this while reading the file. The major problem is that both files use fonts, which they do not supply. Whenever this happens you *will* get font substitution, even with Acrobat. The reason Acrobat behaves differently is that on installation it adds the fonts in your Windows font folder to the ones it can use. You can do this for Ghostscript too by adding -sFONTPATH= and possibly by modifying the fontmap.gs file (which will require you downloading the GS sources) – KenS Dec 12 '13 at 12:15
  • There are a number of answers already here on SO about adding fonts to GS so I won't go into that. WHat other problems do you see with these files ? – KenS Dec 12 '13 at 12:16
2

You could use GSPRINT.

I've managed to make it work by only copying gsprint.exe/gswin64c.exe/gsdll64.dll in a directory and launch it from there.

sample code :

    // This uses gsprint (mind the paths)
    private const string gsPrintExecutable = @"C:\gs\gsprint.exe";
    private const string gsExecutable = @"C:\gs\gswin64c.exe";

    string pdfPath = @"C:\myShinyPDF.PDF"
    string printerName = "MY PRINTER";


    string processArgs = string.Format("-ghostscript \"{0}\" -copies=1 -all -printer \"{1}\" \"{2}\"", gsExecutable, printerName, pdfPath );

            var gsProcessInfo = new ProcessStartInfo
                                    {
                                        WindowStyle = ProcessWindowStyle.Hidden,
                                        FileName = gsPrintExecutable ,
                                        Arguments = processArgs
                                    };
            using (var gsProcess = Process.Start(gsProcessInfo))
            {

                gsProcess.WaitForExit();

            }
0

Try the following command within Process.Start():

gswin32c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOPROMPT -dNoCancel -dPDFFitPage -sOutputFile="%printer%\\[printer_servername]\[printername]" "[filepath_to_pdf]"

It should look like this in C#:

string strCmdText = "gswin32c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOPROMPT -dNoCancel -dPDFFitPage -sOutputFile=\"%printer%\\\\[printer_servername]\\[printername]\" \"[filepath_to_pdf]\"";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);

This will place the specified PDF file into the print queue.

Note- your gswin32c.exe must be in the same directory as your C# program. I haven't tested this code.

Callum Watkins
  • 2,844
  • 4
  • 29
  • 49
Ensai Tankado
  • 189
  • 1
  • 4