C# - 无法捕捉到打印结束

时间:2016-05-10 07:16:31

标签: c# printing printdocument printqueue

我有一台打印机(HP PageWide MFP P57750)通过以太网电缆连接到专用网络。在简单的C#Web App中,用户将pdf文件发送到打印机并设置要打印的份数。在打印结束时,应用程序应通知作业结束。

我尝试使用PrintDocument的EndPrint事件,但它似乎在错误的时间触发,导致打印机仍在打印。

我也尝试将PrintQueue与PrintJobInfoCollection一起使用,但它第一次返回“Printing”PrintJobStatus。然后,我等待5秒钟并重新检查状态,但在打印机仍在打印时队列中没有作业!

我在控制面板中看到 - >设备和打印机的工作进度。即使有许多副本并且打印机仍在打印,打印仅持续几秒钟。我认为在客户端将要打印的文件发送到打印机后,作业将被删除。

我怎样才能抓住真正的印刷结束?

PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile(filePath);
pdf.PrinterName = CicloStampa.Properties.Settings.Default.NomeStampante;
pdf.PrintDocument.PrinterSettings.Copies = (short)numeroCopie;          

pdf.PrintDocument.Print();

PrintServer myPrintServer = new PrintServer();
PrintQueue pq = myPrintServer.GetPrintQueue(CicloStampa.Properties.Settings.Default.NomeStampante);
var printing = true;

while (printing)
{
    pq.Refresh();
    PrintJobInfoCollection pCollection = pq.GetPrintJobInfoCollection();

    foreach (PrintSystemJobInfo job in pCollection)
    {
       //SpotTroubleUsingJobAttributes returns KO/OK by matching PrintJobStatus. First time returns PrintJobStatus.Priting. Second time, pCollection is empty and the printer is still printing.
       var res = SpotTroubleUsingJobAttributes(job);
       System.IO.File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory + @"\Logs\LogImportazione.txt", DateTime.Now.ToString() + " ---- \t\t\t RES: " + res + "\n");
       if (res.StartsWith("KO"))
       {
          //DO STUFF                       
       }
       else
       {
          //END OF PRINT
          printing = false;
        }
     }
     if (pCollection.Count() == 0)
     {                                    
        printing = false;
     }
     if (printing)
     {                                                                       
         System.Threading.Thread.Sleep(5000);
     }
}

2 个答案:

答案 0 :(得分:1)

您可以获取打印队列上的作业集合,然后继续循环,直到获得您要查找的作业状态。

        var myPrintServer = new LocalPrintServer();
        var pq = myPrintServer.GetPrintQueue("Printer Name");

        var jobs = pq.GetPrintJobInfoCollection();

        foreach (var job in jobs)
        {
            var done = false;
            while (!done)
            {
                pq.Refresh();
                job.Refresh();
                done = job.IsCompleted || job.IsDeleted || job.IsPrinted;
            }
        }

修改

PrintQueue还有IsPrinting,IsWaiting,IsBusy等属性,你可以在你的while循环中查看这些属性,但是这些会告诉你一般的打印机,而不是你的工作,所以如果其他人决定打印时你可能会得到误导性的信息

答案 1 :(得分:1)

所以我一直在使用 PDF24 打印机,但这应该适用于所有打印机。

感谢@mark_h 提供代码。使用他的代码示例,我设法找到了一种方法来了解打印队列何时“完成”。您将不得不在打印之前暂停打印队列,因此根据情况,应该留出一些执行时间。

添加到打印队列后,我会计算其中的文档数,以便知道打印机何时打印完所有文档。然后在第二个循环中,我们将在打印文档时不断减去文档。一旦我们到达队列中的最后一个文档,我们就会跳出循环并让线程休眠几秒钟,让打印机有时间完成它。

然后我们可以自由地执行任何代码,因为知道打印作业已经全部打印完毕。

为了赶上打印结束,以下代码将起作用:

            PrintServer printS = new PrintServer();
            PrintQueue printQ = new PrintQueue(printS, "PDF24", PrintSystemDesiredAccess.AdministratePrinter);
            printQ.Pause();


            // Now right here place printing logic, after queue is paused

          
            PrintJobInfoCollection jobs = printQ.GetPrintJobInfoCollection();
            int printCount = 0;

            foreach (var job in jobs)
            {
                printCount++;
            }

            printQ.Resume();

            foreach (var job in jobs)
            {
                var done = false;

                while (!done)
                {
                    printQ.Refresh();
                    job.Refresh();
                    done = job.IsCompleted || job.IsDeleted || job.IsPrinted;
                }

                if (done)
                {
                    printCount--;
                }

                if (printCount < 1)
                {
                    break;
                }
            }

            // Allow some time for the last document to execute, then run what ever code you want
            Thread.Sleep(3000);

我希望这会有所帮助,否则请发表评论,如果需要,我可以提供更多代码示例。真不敢相信要弄清楚打印机是否完成了打印。