0

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

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

我也尝试将 PrintQueue 与 PrintJobInfoCollection 一起使用,但它只是第一次返回“正在打印”的 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);
     }
}
4

2 回答 2

2

所以我一直在使用 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);

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

于 2021-01-19T08:26:57.093 回答
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 循环中查看这些属性,但这些属性通常会告诉您有关打印机的信息,而不是具体有关您的作业的信息,因此如果其他人决定在您打印时你会得到误导性信息吗

于 2016-05-10T07:39:45.470 回答