0

I am trying to print pdf from windows application in my project with iTextSharp dll..

But,The methods I have used till now doesn't seems to be reliable.(Sometimes it work and sometime it doesn't)

I am combining the whole process in a Process class and writing the followin code.

                            printProcess = new Process[noOfCopies];
 // Print number of copies specified in configuration file
                            for (int counter = 0; counter < noOfCopies; counter++)
                            {
                                printProcess[counter] = new Process();

                                // Set the process information
                                printProcess[counter].StartInfo = new ProcessStartInfo()
                                {
                                    CreateNoWindow = true,
                                    Verb = "Print",
                                    FileName = pdfFilePath,
                                    ErrorDialog = false,
                                    WindowStyle = ProcessWindowStyle.Hidden,
                                    UseShellExecute = true,
                                };


    // Start the printing process and wait for exit for 7 seconds
                                    printProcess[counter].Start();

                                    // printProcess[counter].WaitForInputIdle(waitTimeForPrintOut);
                                    printProcess[counter].WaitForExit(waitTimeForPrintOut); //<--**This is line for discussion**

                                    if (!printProcess[counter].HasExited)
                                    {
                                        printProcess[counter].Kill();
                                    }
                                }
   // Delete the file before showing any message for security reason
                        File.Delete(pdfFilePath);

The problem is that if,no pdf is open then the process works fine...(It prints well).But if any pdf is open then WaitForExit(..) method just doesn't waits for the process to exit..and hence the process runs too fast and as I am deleting the file after print it gives error if counter(no of times..) for printing report is more than once..

I have also used Timer to slow the process but it just doesn't works.I don't know why. Used Sleep command too..but it makes main thread to go to sleep and hence doesn't suits me either.

Please suggest me some really reliable way to do so..:)

Ant Radha
  • 2,233
  • 1
  • 13
  • 16
Rahul Ranjan
  • 1,028
  • 1
  • 10
  • 27
  • What application is associate with the print command? I ask because we encountered a similar problem while using the Adobe Reader, and moved to the Foxit Reader. We then started a process using its command line rather than the verb. Seemed to work, and I believe it honored WaitForExit. – Todd Richardson Nov 02 '12 at 13:32

2 Answers2

2

I do not know what kind of application you are trying to print from but a real easy way to print documents or pdfs is to simply copy the file to the printer queue and it will handle everything for you. Very reliable. Just have to have adobe reader installed on the machine printing and the correct driver for the printer. Example code:

        var printer = PrinterHelper.GetAllPrinters().FirstOrDefault(p => p.Default);
        PrinterHelper.SendFileToPrinter("C:\\Users\\Public\\Documents\\Form - Career Advancement Request.pdf", printer.Name);

Printer Helper code:

    public static class PrinterHelper
    {
        public class PrinterSettings
        {
            public string Name { get; set; }
            public string ServerName { get; set; }
            public string DeviceId { get; set; }
            public string ShareName { get; set; }
            public string Comment { get; set; }
            public bool Default { get; set; }
        }

    /// <summary>
    /// Sends the file to printer.
    /// </summary>
    /// <param name="filePathAndName">Name of the file path and Name of File.</param>
    /// <param name="printerName">Name of the printer with Path. E.I. \\PRINT2.company.net\P14401</param>
        public static void SendFileToPrinter(string filePathAndName, string printerName)
        {
            FileInfo file = new FileInfo(filePathAndName);
            file.CopyTo(printerName);
        }

        /// <summary>
        /// Gets all printers that have drivers installed on the calling machine.
        /// </summary>
        /// <returns></returns>
        public static List<PrinterSettings> GetAllPrinters()
        {
            ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Printer");
            ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
            List<PrinterSettings> printers = new List<PrinterSettings>();

            foreach (ManagementObject mo in mos.Get())
            {
                PrinterSettings printer = new PrinterSettings();
                foreach (PropertyData property in mo.Properties)
                {
                    if (property.Name == "Name")
                        printer.Name = property.Value == null ? "" : property.Value.ToString();

                    if (property.Name == "ServerName")
                        printer.ServerName = property.Value == null ? "" : property.Value.ToString();

                    if (property.Name == "DeviceId")
                        printer.DeviceId = property.Value == null ? "" : property.Value.ToString();

                    if (property.Name == "ShareName")
                        printer.ShareName = property.Value == null ? "" : property.Value.ToString();

                    if (property.Name == "Comment")
                        printer.Comment = property.Value == null ? "" : property.Value.ToString();

                    if (property.Name == "Default")
                        printer.Default = (bool)property.Value;
                }
                printers.Add(printer);
            }

            return printers;
        }      
}
retslig
  • 888
  • 5
  • 22
  • Your first parameter of SendFileToPrinter(..) method says 'filePathAndName' in the definition but you have passed printer name at the beginning..It's quite confusing....!! Please clarify on this regard.. – Rahul Ranjan Nov 02 '12 at 14:25
  • Good point ops after further investigation I have the parms swapped. The filePathAndName is the pdf you want to print and the name is for the printer. sorry! – retslig Nov 02 '12 at 14:54
  • Thanks for your quick response..But it gives error as 'Unauthorized access' as it is a network printer...:( – Rahul Ranjan Nov 02 '12 at 16:16
  • Ahh, I am a domain admin on my network... I do not know the permission level necessarily but I am willing to bet if you logon to that printer you could find those permissions. Or get help from your IT staff etc... Then use a user who has those privileges... – retslig Nov 02 '12 at 16:27
0

Try this, you need .net 4 or above. And System.Threading.Tasks

  printProcess = new Process[noOfCopies];
  // Print number of copies specified in configuration file
  Parallel.For(0, noOfCopies, i =>
  {
    printProcess[i] = new Process();

    // Set the process information
    printProcess[i].StartInfo = new ProcessStartInfo()
    {
      CreateNoWindow = true,
      Verb = "Print",
      FileName = pdfFilePath,
      ErrorDialog = false,
      WindowStyle = ProcessWindowStyle.Hidden,
      UseShellExecute = true,
    };


    // Start the printing process and wait for exit for 7 seconds
    printProcess[i].Start();

    // printProcess[counter].WaitForInputIdle(waitTimeForPrintOut);
    printProcess[counter].WaitForExit(waitTimeForPrintOut); //<--**This is line for discussion**

    if(!printProcess[i].HasExited)
    {
      printProcess[i].Kill();
    }
  });
  // Delete the file before showing any message for security reason
  File.Delete(pdfFilePath);
Ant Radha
  • 2,233
  • 1
  • 13
  • 16
  • It's working fine if abobe reader is not already opened. If adobe reader is already opened then it does not wait on WaitForExit(). – Rahul Ranjan Nov 02 '12 at 14:08