DevOvercome
DevOvercome

Reputation: 151

Can't get print job notification with status JOB_STATUS_DELETED

I want to get notification when print job has been completed or deleted. Now I see that notification mechanism provides the JOB_STATUS_DELETING, but no JOB_STATUS_DELETED status can be got.

I found something similar Here, but it doesn't solve my problem.

I'm doing next thing:

  HANDLE hChange = FindFirstPrinterChangeNotification(hPrinter,
                                                      PRINTER_CHANGE_ALL,
                                                      0, 
                                                      &NotificationOptions);

  DWORD dwChange;
  HANDLE aHandles[2];
  aHandles[0] = hChange;
  aHandles[1] = owner->GetStopRequestEvent();

  while (hChange != INVALID_HANDLE_VALUE)
  {
      // sleep until a printer change notification wakes this thread or the
      // event becomes set indicating it's time for the thread to end.
      WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);

      if (WaitForSingleObject(hChange, 0U) == WAIT_OBJECT_0)
      {
          FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);

          if (pNotification != NULL)
          {
              // if a notification overflow occurred,
              if (pNotification->Flags & PRINTER_NOTIFY_INFO_DISCARDED)
              {
                  DWORD dwOldFlags = NotificationOptions.Flags;

                  // we must refresh to continue
                  NotificationOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;

                  FreePrinterNotifyInfo(pNotification);

                  FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);

                  NotificationOptions.Flags = dwOldFlags;
              }

              // iterate through each notification
              for (DWORD x = 0; x < pNotification->Count; x++)
              {
                  PRINTER_NOTIFY_INFO_DATA data = pNotification->aData[x];

                  if (data.Type == JOB_NOTIFY_TYPE)
                  {
                      if (data.Field == JOB_NOTIFY_FIELD_STATUS)
                      {
                          if (data.NotifyData.adwData[0] & ( JOB_STATUS_DELETED | JOB_STATUS_DELETING | JOB_STATUS_PRINTED))
                          {
                              owner->SendJobsData(data.NotifyData.adwData[0]);
                          }   
                ......

when i delete job, JOB_NOTIFY_FIELD_STATUS passes only DELETING, and no any further status-notification, but I really need to get DELETED status. What am I doing wrong?

full code of poller method here: void Poll(JobTracker* owner, CServiceBase* service) { HANDLE hPrinter = NULL; HANDLE hNotification; if (!OpenPrinter(owner -> GetPrinterName(), &hPrinter, NULL)) return;

PPRINTER_NOTIFY_INFO pNotification = NULL;

  WORD JobFields[] = 
  {
      JOB_NOTIFY_FIELD_PRINTER_NAME,
      JOB_NOTIFY_FIELD_MACHINE_NAME,
      JOB_NOTIFY_FIELD_PORT_NAME,
      JOB_NOTIFY_FIELD_USER_NAME,
      JOB_NOTIFY_FIELD_NOTIFY_NAME,
      JOB_NOTIFY_FIELD_DATATYPE,
      JOB_NOTIFY_FIELD_PRINT_PROCESSOR,
      JOB_NOTIFY_FIELD_PARAMETERS,
      JOB_NOTIFY_FIELD_DRIVER_NAME,
      JOB_NOTIFY_FIELD_DEVMODE,
      JOB_NOTIFY_FIELD_STATUS,
      JOB_NOTIFY_FIELD_STATUS_STRING,
      JOB_NOTIFY_FIELD_DOCUMENT,
      JOB_NOTIFY_FIELD_PRIORITY,
      JOB_NOTIFY_FIELD_POSITION,
      JOB_NOTIFY_FIELD_SUBMITTED,
      JOB_NOTIFY_FIELD_START_TIME,
      JOB_NOTIFY_FIELD_UNTIL_TIME,
      JOB_NOTIFY_FIELD_TIME,
      JOB_NOTIFY_FIELD_TOTAL_PAGES,
      JOB_NOTIFY_FIELD_PAGES_PRINTED,
      JOB_NOTIFY_FIELD_TOTAL_BYTES,
      JOB_NOTIFY_FIELD_BYTES_PRINTED
  };
  PRINTER_NOTIFY_OPTIONS_TYPE Notifications[1] =                  
  {
      {
          JOB_NOTIFY_TYPE,
          0,
          0,
          0,
          sizeof(JobFields) / sizeof(JobFields[0]),
          JobFields
      },
  };
  PRINTER_NOTIFY_OPTIONS NotificationOptions = 
  {
      2,
      PRINTER_NOTIFY_OPTIONS_REFRESH,
      sizeof(Notifications) / sizeof(Notifications[0]),
      Notifications
  };

  // get a handle to a printer change notification object.
  HANDLE hChange = FindFirstPrinterChangeNotification(hPrinter,
                                                      PRINTER_CHANGE_ALL,
                                                      0, 
                                                      &NotificationOptions);

  DWORD dwChange;
  HANDLE aHandles[2];
  aHandles[0] = hChange;
  aHandles[1] = owner->GetStopRequestEvent();

  while (hChange != INVALID_HANDLE_VALUE)
  {
      // sleep until a printer change notification wakes this thread or the
      // event becomes set indicating it's time for the thread to end.
      WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);

      if (WaitForSingleObject(hChange, 0U) == WAIT_OBJECT_0)
      {
          FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);

          if (pNotification != NULL)
          {
              // if a notification overflow occurred,
              if (pNotification->Flags & PRINTER_NOTIFY_INFO_DISCARDED)
              {
                  DWORD dwOldFlags = NotificationOptions.Flags;

                  // we must refresh to continue
                  NotificationOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;

                  FreePrinterNotifyInfo(pNotification);

                  FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);

                  NotificationOptions.Flags = dwOldFlags;
              }

              // iterate through each notification
              for (DWORD x = 0; x < pNotification->Count; x++)
              {
                  PRINTER_NOTIFY_INFO_DATA data = pNotification->aData[x];

                  if (data.Type == JOB_NOTIFY_TYPE)
                  {
                      if (data.Field == JOB_NOTIFY_FIELD_STATUS)
                      {
                          if (data.NotifyData.adwData[0] & ( JOB_STATUS_DELETED | JOB_STATUS_DELETING | JOB_STATUS_PRINTED))
                          {
                              owner->SendJobsData(data.NotifyData.adwData[0]);
                          }   
                      }
                      if (data.Field == JOB_NOTIFY_FIELD_STATUS_STRING)
                      {
                          int a = 0;
                      }
                  }
                  else if (data.Type == PRINTER_NOTIFY_TYPE)
                  {
                      if (data.Field == PRINTER_NOTIFY_FIELD_STATUS)
                      {
                          int a = 0;
                      }
                      if (data.Field == PRINTER_NOTIFY_FIELD_STATUS_STRING)
                      {
                          int a = 0;
                      }
                  }
              }
          }

          FreePrinterNotifyInfo(pNotification);
          pNotification = NULL;
      }
      else if (WaitForSingleObject(owner->GetStopRequestEvent(), 0U) == WAIT_OBJECT_0)
      {
          FindClosePrinterChangeNotification(hChange);
          hChange = INVALID_HANDLE_VALUE;
      }
  }

}

Upvotes: 1

Views: 1324

Answers (1)

DevOvercome
DevOvercome

Reputation: 151

If anyone will face such task I will leave my way which I solve it.

I've noticed that every time when job leaves queue, the PRINTER_CHANGE_JOB_DELETE notification (i mean change of FindNextPrinterChangeNotification).

So, I just track task list in thread-owner class (JobTracker), and refresh it every time on any PRINTER_CHANGE_JOB. But before refresh it, I look at the difference and if I see that some job dissapeared (compare by JobId), I take my vector of jobs, and send to server missing job.

Upvotes: 2

Related Questions