Не удается получить уведомление о задании на печать со статусом JOB_STATUS_DELETED

Я хочу получать уведомления, когда задание на печать завершено или удалено. Теперь я вижу, что механизм уведомления предоставляет JOB_STATUS_DELETING, но статус JOB_STATUS_DELETED получить невозможно.

Я нашел что-то похожее здесь, но это не решает моя проблема.

Я делаю следующее:

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

когда я удаляю задание, JOB_NOTIFY_FIELD_STATUS передает только DELETING и никаких дальнейших уведомлений о статусе, но мне действительно нужно получить статус DELETED. Что я делаю неправильно?

полный код метода опроса здесь: void Poll(JobTracker* owner, CServiceBase* service) { HANDLE hPrinter = NULL; HANDLE hNotification; if (!OpenPrinter(владелец -> 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;
      }
  }

}


person DevOvercome    schedule 19.10.2014    source источник
comment
Не похоже, что ты делаешь что-то не так. Ваш вопрос, почему вы никогда не получаете событие JOB_STATUS_DELETING?   -  person Carey Gregory    schedule 20.10.2014
comment
@CareyGregory Нет, мне нужно уведомление JOB_STATUS_DELETED   -  person DevOvercome    schedule 20.10.2014
comment
На практике это одно и то же. Я не думаю, что вы когда-либо увидите статус DELETED, потому что, когда задание будет полностью удалено, GetJob завершится ошибкой, поскольку задания больше не существует.   -  person Carey Gregory    schedule 20.10.2014
comment
@CareyGregory Я так и думал, возможно, мы не можем получить DELETED, потому что работа больше не существует, но я думаю, что дважды видел событие DELETING, знаете ли, когда какой-то другой статус обновлялся, например, добавлялся статус ERROR. Поэтому я боюсь, что скажу веб-серверу, что задание удалено дважды, и это будет нелепой ошибкой и попыткой использовать событие DELETE.   -  person DevOvercome    schedule 20.10.2014
comment
@CareyGregory, кстати, кажется, я столкнулся с проблемой, о которой вы говорите, когда я получил статус PRINTED (сейчас, к сожалению, не могу его получить). На PRINTED I EnumJobs и не вижу никаких заданий для отчета на сервере, потому что оно было удалено сразу после события PRINTED.   -  person DevOvercome    schedule 20.10.2014
comment
@CareyGregory вау, у меня УДАЛЕНИЕ двойных событий. У меня есть коды состояния 22 и 6, что означает печать|удаление и удаление   -  person DevOvercome    schedule 20.10.2014
comment
Я обнаружил, что могу поймать PRINTER_CHANGE_DELETE_JOB сразу после удаления задания. Кроме того, я получил это изменение после печати. Поэтому я считаю, что могу создать JOB_INFO, когда произошло PRINTER_CHANGE_ADD_JOB, если STATUS изменился на DELETING, я могу изменить статус JOB_INFO на DELETED (небольшой обман?), И когда произошло PRINTER_CHANGE_DELETE_JOB, я отправляю на сервер свою сохраненную информацию о JOB, и мне все равно, какой статус имеет было написано здесь в процессе. Дай мне попробовать...   -  person DevOvercome    schedule 20.10.2014


Ответы (1)


Если кто-то столкнется с такой задачей, я оставлю свой путь, которым я ее решаю.

Я заметил, что каждый раз, когда задание покидает очередь, появляется уведомление PRINTER_CHANGE_JOB_DELETE (имеется в виду изменение FindNextPrinterChangeNotification).

Итак, я просто отслеживаю список задач в классе владельца потока (JobTracker) и обновляю его каждый раз при любом PRINTER_CHANGE_JOB. Но прежде чем обновить его, я смотрю на разницу и если вижу, что какая-то работа исчезла (сравните по JobId), я беру свой вектор заданий и отправляю на сервер отсутствующее задание.

person DevOvercome    schedule 20.10.2014
comment
Вы должны принять свой ответ, чтобы вопрос отображался как ответ. - person Carey Gregory; 22.10.2014
comment
@CareyGregory, спасибо, что напомнили! Я хотел сделать это сразу после публикации, но 24-часовой кулдаун не позволил мне этого сделать. - person DevOvercome; 22.10.2014