【问题标题】:System.Printing skips a few job status states?System.Printing 跳过一些作业状态?
【发布时间】:2013-05-12 16:31:21
【问题描述】:

我正在向打印机发送打印作业,并尝试跟踪它们的状态,以便将其反映在我自己的队列中。

似乎打印作业从未经历过“已打印”、“已完成”状态。

我做了一个小测试程序,看看我是否以错误的方式使用了 .net 对象,但这仍然发生。我运行我的测试程序来查询一个新的打印作业,一旦有一个打印作业,我就会对其进行大量轮询并刷新每次以查看其状态并确保我不会错过任何内容。

PrintServer ps = new PrintServer(@"\\printServer");
PrintQueue pq = new PrintQueue(ps, "PDF Writer - bioPDF");
PrintSystemJobInfo jobInfo = null;

while (jobInfo == null)
{
    pq.Refresh();
    var printJobs = pq.GetPrintJobInfoCollection(); 

    foreach (var printJob in printJobs)
    {
        printJob.Refresh();

        jobInfo = printJob;
        break;
    }

    Thread.Sleep(100);
}

PrintJobStatus jobStatus = PrintJobStatus.None;
PrintJobStatus prevJobStatus = PrintJobStatus.None;
while (true)
{
    try
    {
        jobInfo.Refresh();
    } catch { }

    prevJobStatus = jobStatus;
    jobStatus = jobInfo.JobStatus;

    if (jobStatus != prevJobStatus)
    {
        Console.WriteLine("**UPDATE**");
        SpotTroubleUsingProperties(jobInfo); // Microsoft example method that prints a description of each possible job status
    }

    Thread.Sleep(20);
}

即使打印了文档,我得到的结果是:

**UPDATE**
The job is spooling now.
**UPDATE**
The job is printing now.
**UPDATE**
The user or someone with administration rights to the queue has deleted the job. It must be resubmitted.

我如何知道文档何时处于“已完成”状态?

【问题讨论】:

    标签: .net system.printing print-spooler-api


    【解决方案1】:

    除非您为打印机启用“保留打印的文档”选项,否则您永远不会看到Completed 状态,因为打印作业一完成就会被删除。转换是 Printing-->Deleting, 而不是 Printing-->Completed-->Deleting

    因此,您有两个可能的信号表明作业已完成:1) 当它进入 Deleting 状态时和 2) 当它从队列中消失时。据我所知,没有办法区分打印作业是因为完成而被删除,还是因为人或其他程序删除了它。

    【讨论】:

    • 我不知道这个选项。我认为PrintQueue 对象以某种方式为我维护了该数据,但现在我更好地理解了它——因为它只会在我调用Refresh() 时再次对实际的线轴进行采样。在更改您提到的那个选项之后(太糟糕了,它不能以编程方式完成),由于某种原因,当工作完成时,它们仅处于Printed 状态。 KeepPrintedJobsPrintQueue 对象为真,但IsRetainedPrintSystemJobInfo 对象为假。此外,作业的状态为Printed,而不是Completed。这是为什么呢?
    • @shwartz 我不知道为什么。 Windows 的整个打印子系统是从 DOS 和 Windows 3.x 演变而来的一个奇异的、过于复杂的世界,它仍然承载着那个时代的许多包袱。但是,如果您需要 keep-printed-documents 选项,可以通过编程方式进行设置。看看 SetPrinter()、PRINTER_INFO_2 结构和 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 选项。
    • 不,抱歉。 Microsoft 没有费心在托管代码中完成大部分 Win32 API。
    • 好吧,您仍然可以从托管代码调用所有 Win32 API。
    • 如果有人有兴趣以编程方式进行设置:stackoverflow.com/questions/12110010/…
    【解决方案2】:

    我只是在测试类似的情况并开始跟踪日志输出,没有设置“保留打印文档”标志:

    Info: 11/24/2017 12:08:18 PM - JobStatus for document testA4.pdf is Printing, Retained.
    Info: 11/24/2017 12:08:22 PM - JobStatus for document testA4.pdf changed from Printing, Retained to Retained.
    Info: 11/24/2017 12:08:22 PM - JobStatus for document testA4.pdf changed from Retained to Completed, Retained.
    Info: 11/24/2017 12:08:22 PM - Document testA4.pdf marked as Completed by printer.
    Info: 11/24/2017 12:08:33 PM - JobStatus for document testA4.pdf changed from Completed, Retained to Deleted.
    

    似乎它可能取决于打印机/驱动程序。

    用于获取此输出的代码:

    public void MonitorPrintJobStatus(string printerName, Document document, CancellationToken token)
    {
        using (var printServer = new LocalPrintServer())
        {
            using (var printQueue = printServer.GetPrintQueue(printerName))
            {
                foreach (var printJobInfo in printQueue.GetPrintJobInfoCollection())
                {
                    if (printJobInfo.Name == document.DocumentToBePrinted.Path)
                    {
                        bool printed = false;
                        var previousPrintJobStatus = printJobInfo.JobStatus;
                        _logger.LogInfo($"{DateTime.Now} - JobStatus for document {document.DocumentToBePrinted.Path} is {previousPrintJobStatus}.");
                        while (!token.IsCancellationRequested && !printed)
                        {
                            printJobInfo.Refresh();
                            if (previousPrintJobStatus != printJobInfo.JobStatus)
                            {
                                _logger.LogInfo($"{DateTime.Now} - JobStatus for document {document.DocumentToBePrinted.Path} changed from {previousPrintJobStatus} to {printJobInfo.JobStatus}.");
                                previousPrintJobStatus = printJobInfo.JobStatus;
                            }
                            if (printJobInfo.IsCompleted)
                            {
                                _logger.LogInfo($"{DateTime.Now} - Document {document.DocumentToBePrinted.Path} marked as Completed by printer.");
                                document.Status = DocumentPrintStatus.Printed;
                                printed = true;
                            }
                        }
                        break;
                    }
                }
            }
        }
    }
    

    【讨论】:

    • 有趣。也许从完成到删除的过渡是如此之快,以至于只有像您这样的轮询循环才能看到它。感谢您的信息。
    • 好吧,如果您查看日志,您会发现“删除”大约需要 11 秒 ?
    猜你喜欢
    • 2020-09-08
    • 1970-01-01
    • 2020-05-09
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2023-01-04
    • 2021-10-12
    相关资源
    最近更新 更多