Ejemplo n.º 1
0
        /// <summary>
        /// Prints a document using interop services.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
        /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
        protected override FilePrintResult PrintInterop(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            ProcessUtil.KillProcess("POWERPNT");

            Application   powerpoint    = null;
            Presentations presentations = null;
            Presentation  presentation  = null;

            try
            {
                OnStatusChanged("Starting PowerPoint");
                powerpoint = new Application();
                powerpoint.DisplayAlerts = PpAlertLevel.ppAlertsNone;

                OnStatusChanged("Opening file: " + file.Name);
                presentations = powerpoint.Presentations;
                presentation  = presentations.Open(file.FullName,
                                                   ReadOnly: MsoTriState.msoCTrue,
                                                   WithWindow: MsoTriState.msoFalse);

                // Check for the word "on" in the queue name.  If it exists, include the port in the name.
                string queueName = printQueue.FullName;
                if (queueName.Contains(" on ") || queueName.StartsWith("on ", false, CultureInfo.CurrentCulture) || queueName.EndsWith(" on", false, CultureInfo.CurrentCulture))
                {
                    queueName = GetQueueNameWithPort(printQueue);
                }

                try
                {
                    OnStatusChanged($"Setting active printer to {queueName}");
                    presentation.PrintOptions.ActivePrinter = queueName;
                }
                catch
                {
                    throw new FilePrintException($"PowerPoint cannot print to '{queueName}'.  Check the formatting of the queue name.");
                }

                OnStatusChanged("Printing to: " + queueName);
                DateTimeOffset startTime = DateTimeOffset.Now;
                presentation.PrintOptions.PrintInBackground = MsoTriState.msoFalse;
                presentation.PrintOut(Copies: printOptions.Copies, Collate: MsoTriState.msoFalse);
                DateTimeOffset endtime = DateTimeOffset.Now;

                OnStatusChanged("Closing presentation...");
                presentation.Close();

                OnStatusChanged("Quitting PowerPoint.");
                powerpoint.Quit();

                return(new FilePrintResult(startTime, endtime));
            }
            finally
            {
                if (presentation != null)
                {
                    Marshal.FinalReleaseComObject(presentation);
                    presentation = null;
                }

                if (presentations != null)
                {
                    Marshal.FinalReleaseComObject(presentations);
                    presentations = null;
                }

                if (powerpoint != null)
                {
                    Marshal.FinalReleaseComObject(powerpoint);
                    powerpoint = null;
                }

                GarbageCollect();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Prints a document using interop services.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
        /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
        protected override FilePrintResult PrintInterop(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            ProcessUtil.KillProcess("WINWORD");

            Application word      = null;
            Documents   documents = null;
            Document    document  = null;

            try
            {
                OnStatusChanged("Starting Word");
                word = new Application();

                OnStatusChanged("Opening file: " + file.Name);
                documents = word.Documents;
                document  = documents.Open(file.FullName, ReadOnly: true, Visible: true);

                // Check for the word "on" in the queue name.  If it exists, include the port in the name.
                string queueName = printQueue.FullName;
                if (queueName.Contains(" on ") || queueName.StartsWith("on ", false, CultureInfo.CurrentCulture) || queueName.EndsWith(" on", false, CultureInfo.CurrentCulture))
                {
                    queueName = GetQueueNameWithPort(printQueue);
                }

                try
                {
                    OnStatusChanged($"Setting active printer to {queueName}");
                    word.ActivePrinter = queueName;
                }
                catch
                {
                    throw new FilePrintException($"Word cannot print to '{queueName}'.  Check the formatting of the queue name.");
                }

                OnStatusChanged("Printing to: " + queueName);
                DateTimeOffset startTime = DateTimeOffset.Now;
                document.PrintOut(Background: false,
                                  Append: false,
                                  Range: WdPrintOutRange.wdPrintAllDocument,
                                  Item: WdPrintOutItem.wdPrintDocumentContent,
                                  Copies: printOptions.Copies.ToString(),
                                  PageType: WdPrintOutPages.wdPrintAllPages,
                                  PrintToFile: false,
                                  Collate: true,
                                  ManualDuplexPrint: false);
                DateTimeOffset endTime = DateTimeOffset.Now;

                OnStatusChanged("Closing document...");
                document.Close(WdSaveOptions.wdDoNotSaveChanges, WdOriginalFormat.wdOriginalDocumentFormat, false);

                OnStatusChanged("Quitting Word.");
                word.Quit(WdSaveOptions.wdDoNotSaveChanges, WdOriginalFormat.wdOriginalDocumentFormat, false);

                return(new FilePrintResult(startTime, endTime));
            }
            finally
            {
                if (document != null)
                {
                    Marshal.FinalReleaseComObject(document);
                    document = null;
                }

                if (documents != null)
                {
                    Marshal.FinalReleaseComObject(documents);
                    documents = null;
                }

                if (word != null)
                {
                    Marshal.FinalReleaseComObject(word);
                    word = null;
                }

                GarbageCollect();
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Prints a document using interop services.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
        /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
        protected override FilePrintResult PrintInterop(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            ProcessUtil.KillProcess("EXCEL");

            Application excel  = null;
            Workbooks   wbooks = null;
            Workbook    wbook  = null;

            try
            {
                OnStatusChanged("Starting Excel");
                excel = new Application {
                    DisplayAlerts = false
                };

                OnStatusChanged("Opening file: " + file.Name);
                wbooks = excel.Workbooks;
                wbook  = wbooks.Open(file.FullName,
                                     UpdateLinks: 0,
                                     ReadOnly: true,
                                     IgnoreReadOnlyRecommended: true,
                                     CorruptLoad: XlCorruptLoad.xlRepairFile);

                // Excel 2010 must have the port appended to the queue name in order to print.
                string queueName = GetQueueNameWithPort(printQueue);
                try
                {
                    OnStatusChanged($"Setting active printer to {queueName}");
                    excel.ActivePrinter = queueName;
                }
                catch (Exception ex)
                {
                    throw new FilePrintException($"Excel cannot print to '{queueName}'.  Check the formatting of the queue name.", ex);
                }

                OnStatusChanged("Printing to: " + queueName);
                DateTimeOffset startTime = DateTimeOffset.Now;

                //few excel documents threw exception when using sheets.Printout method but didn't when using the workbook method. We are now using workbook method to print
                wbook.PrintOut(Copies: printOptions.Copies, Preview: false);
                DateTimeOffset endtime = DateTimeOffset.Now;

                OnStatusChanged("Closing workbook...");
                wbook.Close();
                wbooks.Close();

                OnStatusChanged("Quitting Excel.");
                excel.Quit();

                return(new FilePrintResult(startTime, endtime));
            }
            finally
            {
                if (wbook != null)
                {
                    Marshal.FinalReleaseComObject(wbook);
                    wbook = null;
                }

                if (wbooks != null)
                {
                    Marshal.FinalReleaseComObject(wbooks);
                    wbooks = null;
                }

                if (excel != null)
                {
                    Marshal.FinalReleaseComObject(excel);
                    excel = null;
                }

                GarbageCollect();
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Prints the specified file to the specified print queue.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
        /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="file" /> is null.
        /// <para>or</para>
        /// <paramref name="printQueue" /> is null.
        /// </exception>
        /// <exception cref="FilePrintException">An error occurred while printing the file.</exception>
        protected override FilePrintResult PrintFile(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (printQueue == null)
            {
                throw new ArgumentNullException(nameof(printQueue));
            }

            // Adobe Reader provides command line arguments that can be used to launch a new instance,
            // print a document, and then close automatically.  If we wait for the process to finish,
            // we know that the job is done printing.

            // However... Adobe Reader refuses to automatically close if it is the only instance of Reader
            // running on the machine.  In order to force the process to end so that we are notified
            // when the job is finished printing, we have to make sure there is a "dummy" instance of
            // Reader running.  This "dummy" instance serves no purpose other than to make sure that the
            // "real" instances we use to print will exit when they are done.

            // NOTE: The dummy cannot be cleaned up after the print is complete.  This is because
            // there is no way to differentiate between the "dummy" we created and other legitimate
            // printing processes that may be happening on other threads.  The dummy is an unfortunate
            // leftover from the automation process.

            // To avoid spawning multiple dummies, only create one if no dummy currently exists
            if (!Process.GetProcessesByName(_applicationName).Any())
            {
                LogTrace($"Creating dummy PDF process.");
                Process.Start(_applicationName, "/h");
                Thread.Sleep(5000);
            }

            string           args             = string.Format(" /N /T \"{0}\" \"{1}\"", file.FullName, printQueue.FullName);
            ProcessStartInfo processStartInfo = new ProcessStartInfo(_applicationName, args);

            return(PrintFileViaProcess(file, processStartInfo, false));
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Prints the specified file to the specified print queue.
 /// </summary>
 /// <param name="file">The file to print.</param>
 /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
 /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
 /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="file" /> is null.
 /// <para>or</para>
 /// <paramref name="printQueue" /> is null.
 /// </exception>
 /// <exception cref="FilePrintException">An error occurred while printing the file.</exception>
 protected override FilePrintResult PrintFile(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
 {
     // By default, use the PrintTo verb
     return(PrintFile(file, printQueue, PrintVerb.PrintTo));
 }
        protected sealed override FilePrintResult PrintFile(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            // Check to see if this is the first time this user has printed with MS office.
            if (!_users.Contains(Environment.UserName))
            {
                OnStatusChanged($"Applying first run policies for {Environment.UserName}.");
                ApplyFirstRunPolicies();
                _users.Add(Environment.UserName);
            }

            // Print the document using COM interop, retrying in the event of timeouts and enforcing a 10 minute time limit.
            try
            {
                int retries = 0;
                while (true)
                {
                    try
                    {
                        FilePrintResult result  = null;
                        void action() => result = PrintInterop(file, printQueue, printOptions);

                        using (InteropTimedTask task = new InteropTimedTask(TimeSpan.FromMinutes(10)))
                        {
                            OnStatusChanged("Beginning interop print.");
                            task.Run(action);
                            OnStatusChanged("Document finished printing.");
                        }
                        return(result);
                    }
                    catch (COMException ex) when(ex.ErrorCode == _hResultTimeout && retries < 5)
                    {
                        retries++;
                        OnStatusChanged($"Caught exception: {ex.Message}, trying again (attempt #{retries})");
                    }
                    catch (COMException ex)
                    {
                        OnStatusChanged($"Caught exception: {ex.Message}, aborting print.");
                        throw new FilePrintException(ex.Message, ex);
                    }
                }
            }
            finally
            {
                DeleteTempFiles();
            }
        }
 /// <summary>
 /// Prints a document using interop services.  Must be implemented by inheriting classes.
 /// </summary>
 /// <param name="file">The file to print.</param>
 /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
 /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
 /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
 protected abstract FilePrintResult PrintInterop(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions);
Ejemplo n.º 8
0
        /// <summary>
        /// Prints the specified file to the specified print queue.
        /// </summary>
        /// <param name="file">The file to print.</param>
        /// <param name="printQueue">The <see cref="PrintQueue" /> to print the file to.</param>
        /// <param name="printOptions">The <see cref="FilePrintOptions" /> to use for printing the file.</param>
        /// <returns>A <see cref="FilePrintResult" /> object representing the outcome of the print operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="file"/> is null.
        /// <para>or</para>
        /// <paramref name="printQueue"/> is null.
        /// </exception>
        /// <exception cref="FilePrintException">An error occurred while printing the file.</exception>
        protected override FilePrintResult PrintFile(FileInfo file, PrintQueue printQueue, FilePrintOptions printOptions)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (printQueue == null)
            {
                throw new ArgumentNullException(nameof(printQueue));
            }

            ProcessStartInfo processStartInfo = new ProcessStartInfo
            {
                FileName        = _applicationName,
                Arguments       = string.Format(" /PT \"{0}\" \"{1}\"", file.FullName, printQueue.FullName),
                CreateNoWindow  = true,
                WindowStyle     = ProcessWindowStyle.Hidden,
                UseShellExecute = true,
                ErrorDialog     = false
            };

            return(PrintFileViaProcess(file, processStartInfo));
        }