Reputation: 151
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
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