Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Printing PDF using Ghostscript in C#

5.00/5 (3 votes)
29 Sep 2016CPOL1 min read 26.1K  
How to print PDF using Ghostscript in C#

This logic will print PDF documents, using GhostScript, without opening or using Adobe.
You will need to have Ghostscript installed on the local system for this to work

Finding a PDF Application 
This finds the GhostScript exe application path

Create Pool of reg keys
This is the pool of different possibilities of registration keys, which will contain the path to the exe 

private static void createRegistrationKey()
       {

           RegistrationKey = new Liststring, string>>();
           RegistrationKey.Add(new Tuple<string, string>("Ghost", @"SOFTWARE\GPL Ghostscript"));
           RegistrationKey.Add(new Tuple<string, string>("Ghost",@"SOFTWARE\AFPL Ghostscript"));
         }

Get path from the registration
Using data from the pool it will check the reg for the exe path, The ghostscript does not contain the value in the primary key, it within the sub key.
Once within the sub key, the path returned is the root path or dll. So I have done a small hack to the code which will return the exe file, if this pathway is hit (ONLY because, I know that the exe name is correct)

private static Tuple<string,string> getRegistryApplicationPath(string keyTitle, string applicationKey)
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey(applicationKey);
            if (key != null)
            {
                if(key.ValueCount > 0)
                {
                    return new Tuple<string, string>(keyTitle, key.GetValue("").ToString());
                }
                else if (key.SubKeyCount > 0)
                {
                    foreach(var item in key.GetSubKeyNames())
                    {
                        var inner = key.OpenSubKey(item);
                        foreach(var valueInner in inner.GetValueNames())
                        {
                            string inner1 = inner.GetValue(valueInner).ToString();
                            if (!inner1.Contains(".exe") && !inner1.Contains(".dll") && inner1.Contains("GPLGS"))
                            {
                              //As the folder exists, I will just add the exe name, which I know it will be and return the full path
                                return new Tuple<string, string>(keyTitle, Path.Combine(inner1, "gswin32c.exe"));

                            }else if (inner1.Contains(".exe") || inner1.Contains(".dll"))
                            {
                                return new Tuple<string, string>(keyTitle, Path.Combine(inner1));
                            }

                        }
                    }
                }
                
            }

            return new Tuple<string,string>(String.Empty,String.Empty);
        }

Get installer exe path
Loop through each item within the queue, to see if there is a reg record

private static void getInstalledApplicationPath()
        {
            
            
            foreach (var s in RegistrationKey)
            {
                allocatedPath = getRegistryApplicationPath(s.Item1, s.Item2);
                if (!String.IsNullOrEmpty(allocatedPath.Item1))
                {
                    break;
                }
            }
        }

Allocation controller method
This method controls the allocation logic

public static Tuple<string, string> Allocate()
       {

           createRegistrationKey();
           getInstalledApplicationPath();

           return allocatedPath;
       }

Printing the PDF document 
This uses the Allocation logic to find the exe path and then it sends the document to the printer, without any popups
Create the Process start info object
Creates the ProcessStartInfo object, so GhostScript can print the pdf

private static void setProcess()
    {
      startInfo = new ProcessStartInfo();
        startInfo.Arguments =
            String.Format(
                " -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=mswinpr2 -sOutputFile=\"\\\\spool\\{0}\" \"{1}\"",
                printerName, printFileName);
        startInfo.FileName = applicationPath;
        startInfo.UseShellExecute = false;

    }

Get the current default printer
This get the printer name for the default printer within windows

private static void getPrinterName()
        {
            PrintDialog pt = new PrintDialog();
            printerName = pt.PrinterSettings.PrinterName;

        }

Run the process
Creates controls the creation of the process to send the PDF to the printer

 public static void Print(string path,  string exePath)
        {
            var allocation = PDFLibrary.ApplicationEXEPath.Allocate();
            printFileName = path;
            applicationPath = allocation.Item2;
                  
            getPrinterName();
          
            setTracking();
                       
            
            if (!String.IsNullOrEmpty(applicationPath))
            {
                setProcess();

                using (var process = Process.Start(startInfo))
                {

                    Console.WriteLine("Process started");
                    Console.WriteLine("Process Id: " + process.Id.ToString());
                    Console.WriteLine("Process Machine name: " + process.MachineName.ToString());

                    Console.WriteLine("Wait for Process to exit");
                    process.WaitForExit();                                     

                    Console.WriteLine( "Closing Process");
                    closeProcess(process);                   
                                        
                }
                reJoinThread();

            }
            else
            {
                MessageBox.Show(LanguageHelper.GetString("dlgPDFViewer.CantFindPDFApplication"), "Health Options®", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

private static void closeProcess(Process process)
        {
            try
            {
                process.CloseMainWindow();
                process.Kill();
            }
            catch (Exception e)
            {
                
            }
        }

        private static void reJoinThread()
        {
            try
            {
                Console.WriteLine(""Try and re-join the Tracking thread");
                trackingThread.Join();
               Console.WriteLine(""Thread has ended");
            }
            catch (Exception e)
            {
               
            }

        }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)