无法获得状态为JOB_STATUS_DELETED的打印作业通知

时间:2014-10-19 22:54:36

标签: c++ winapi print-spooler-api

我希望在完成或删除打印作业时收到通知。现在我看到通知机制提供了JOB_STATUS_DELETING,但是没有JOB_STATUS_DELETED状态。

我找到了类似的Here,但它并没有解决我的问题。

我正在做下一件事:

  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状态。我做错了什么?

这里的poller方法的完整代码:     void Poll(JobTracker *所有者,CServiceBase *服务)     {     HANDLE hPrinter = NULL;     处理hNotification;     if(!OpenPrinter(owner - &gt; GetPrinterName(),&amp; hPrinter,NULL))         返回;

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

}

1 个答案:

答案 0 :(得分:2)

如果有人将面临这样的任务,我将离开我解决它的方式。

我注意到,每当作业离队时,PRINTER_CHANGE_JOB_DELETE通知(我的意思是更改FindNextPrinterChangeNotification)。

所以,我只是在线程所有者类(JobTracker)中跟踪任务列表,并且每次在任何PRINTER_CHANGE_JOB上刷新它。但在刷新它之前,我会看一下差异,如果我发现某些工作消失了(通过JobId比较),我会将我的工作向量发送给服务器,并将其发送给服务器。