1

I am sending print jobs to the printer and I try to keep track of their status in order to reflect it in a queue of my own.

It seems as if the print jobs never go through "Printed", "Completed" status.

I made a small test program to see if maybe I was using the .net object the wrong way but this still happened. I ran my test program to query for a new print job and once there was a one I heavily polled it and refreshed every time to see its status and make sure I don't miss anything.

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);
}

The result I get, even though the document is printed, is:

**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.

How can I know when the document is in "Completed" status?

shwartz
  • 631
  • 3
  • 13
  • 29

2 Answers2

3

Unless you enable the "Keep printed documents" option for the printer, you're never going to see the Completed status since print jobs are deleted as soon as they finish. The transition is Printing-->Deleting, not Printing-->Completed-->Deleting.

So you have two possible signals that a job has completed: 1) When it enters the Deleting status and 2) when it vanishes from the queue. To my knowledge, there is no way to distinguish between a print job being deleted because it completed and because a person or other program deleted it.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
  • I was unaware of that option. I thought the ```PrintQueue``` object maintains that data for me somehow but now I understand it better - since it only samples the actual spool again when I call ```Refresh()```. After changing that option you mention (too bad it can't be done programmatically), for some reason, when the jobs are done they are only in ```Printed``` status. ```KeepPrintedJobs``` is true for the ```PrintQueue``` object but ```IsRetained``` is false for the ```PrintSystemJobInfo``` object. Also, jobs are at ```Printed``` status and not ```Completed```. Why is that? – shwartz May 19 '13 at 15:53
  • 1
    @shwartz I don't know why. The entire printing subsystem of Windows is a bizarre, overly complex world that evolved from DOS and Windows 3.x, and it still carries a lot baggage from that era. But if you need the keep-printed-documents option, it can be set programmatically. Take a look at SetPrinter(), the PRINTER_INFO_2 struct, and the PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS option. – Carey Gregory May 19 '13 at 16:23
  • No, sorry. Microsoft didn't bother finishing most of the Win32 API in managed code. – Carey Gregory May 20 '13 at 07:05
  • Well, you can still call all of the Win32 API from managed code. – Carey Gregory May 20 '13 at 07:28
  • Yes, but we're trying to avoid that where possible. We've had some issues with Win32 API code in the past. In this case, I think it would be acceptable for us to set this up manually since I can make my code rather resilient to the case where ```KeepPrintedJobs``` == false. – shwartz May 20 '13 at 08:01
  • 3
    In case someone's interested in setting this programmaticaly: http://stackoverflow.com/questions/12110010/setting-printers-keepprinteddocuments-property-in-net – shwartz May 20 '13 at 08:47
1

I was just testing a similar situation and came to following logging output, without the 'Keep printed documents' flag set:

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.

Seems that it may be printer/driver dependent.

Code used to get this output:

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;
                }
            }
        }
    }
}
Sylvain Girard
  • 368
  • 3
  • 13
  • Interesting. Maybe the transition from completed to deleting is so fast that only a polling loop like you did would ever see it. Thanks for the info. – Carey Gregory Dec 02 '17 at 01:19
  • Well, if you look at the logs you’ll see that it takes about 11 seconds to get to ‘deleted’ – Sylvain Girard Dec 02 '17 at 21:22