Я застрял на проблеме, где я хотел бы попросить некоторую помощь:
У меня есть задача напечатать некоторые файлы разных типов, используя ShellExecuteEx с глаголом «print», и мне нужно гарантировать порядок печати всех файлов. Поэтому я использую FindFirstPrinterChangeNotification и FindNextPrinterChangeNotification для мониторинга событий PRINTER_CHANGE_ADD_JOB и PRINTER_CHANGE_DELETE_JOB, используя два разных потока в фоновом режиме, которые я запускаю перед вызовом ShellExecuteEx, так как я не знаю ничего о приложении, которое будет печатать файлы и т. Д. Я единственный, кто печатает, и какой файл я печатаю. Мое решение, кажется, работает хорошо, моя программа успешно распознает событие PRINTER_CHANGE_ADD_JOB для моего файла, я даже проверяю, что это событие генерируется для моего файла, проверяя то, что мне дают в качестве дополнительной информации, указав JOB_NOTIFY_FIELD_DOCUMENT.
Теперь проблема в событии PRINTER_CHANGE_DELETE_JOB, где я не получаю никакой дополнительной информации о задании на печать, хотя моя логика абсолютно одинакова для обоих событий: я написал одну универсальную функцию потока, которая просто выполняется с событием, которое она используется для. Мой поток распознает событие PRINTER_CHANGE_DELETE_JOB, но при каждом вызове FindNextPrinterChangeNotification всякий раз, когда это событие происходит, я не получаю никаких дополнительных данных в ppPrinterNotifyInfo. Это работает для стартового события, хотя я проверил, используя мои журналы и отладчик. Но с PRINTER_CHANGE_DELETE_JOB я получаю только NULL.
Я уже искал в Интернете, и есть некоторые похожие вопросы, но большую часть времени, связанные с VB или просто без ответа. Я использую проект C ++ и, поскольку мой код работает для события ADD_JOB, я не думаю, что делаю что-то совершенно не так. Но даже MSDN не упоминает об этом, и я действительно хотел бы убедиться, что событие DELETE_JOB является тем для моего документа, что я не могу без какой-либо информации о задании на печать. После того, как я получаю событие DELETE_JOB, мой код даже не распознает другие события, что нормально, потому что задание на печать выполняется позже.
Вот то, что я считаю соответствующим кодом уведомления:
WORD jobNotifyFields[1] = {JOB_NOTIFY_FIELD_DOCUMENT};
PRINTER_NOTIFY_OPTIONS_TYPE pnot[1] = {JOB_NOTIFY_TYPE, 0, 0, 0, 1, jobNotifyFields};
PRINTER_NOTIFY_OPTIONS pno = {2, 0, 1, pnot};
HANDLE defaultPrinter = PrintWaiter::openDefaultPrinter();
HANDLE changeNotification = FindFirstPrinterChangeNotification( defaultPrinter,
threadArgs->event,
0, &pno);
[...]
DWORD waitResult = WAIT_FAILED;
while ((waitResult = WaitForSingleObject(changeNotification, threadArgs->wfsoTimeout)) == WAIT_OBJECT_0)
{
LOG4CXX_DEBUG(logger, L"Irgendein Druckereignis im Thread zum Warten auf Ereignis " << LogStringConv(threadArgs->event) << L" erkannt.");
[...]
PPRINTER_NOTIFY_INFO notifyInfo = NULL;
DWORD events = 0;
FindNextPrinterChangeNotification(changeNotification, &events, NULL, (LPVOID*) ¬ifyInfo);
if (!(events & threadArgs->event) || !notifyInfo || !notifyInfo->Count)
{
LOG4CXX_DEBUG(logger, L"unpassendes Ereignis " << LogStringConv(events) << L" ignoriert");
FreePrinterNotifyInfo(notifyInfo);
continue;
}
[...]
Я был бы очень признателен, если бы кто-нибудь дал несколько советов, почему я не получаю никаких данных, касающихся задания на печать. Спасибо!
https://forums.embarcadero.com/thread.jspa?threadID=86657&stqc = TRUE
Вот что я думаю происходит:
Я наблюдаю два события в двух разных потоках для начала и конца каждого задания на печать. После некоторой отладки и регистрации я обнаружил, что FindNextPrinterChangeNotification не всегда возвращает только два разных события, о которых я уведомил, но некоторые 0-события в целом. В этих случаях FindNextPrinterChangeNotification возвращает 0 как события в pdwChange. Если я печатаю простой текстовый файл с помощью notepad.exe, я получаю только одно событие для создания задания на печать со значением 256 для pdwChange и данными, которые мне нужны в notifyInfo для сравнения имени моего печатаемого файла и сравнения обоих результатов. Если я печатаю файл pdf с использованием текущей версии Acrobat Reader 11, я получаю два события, одно из которых имеет pdwChange как 256, но в качестве имени запущенного задания на печать в качестве имени запускаемого задания на печать выводится что-то вроде «local printdatafile», что, очевидно, не тот файл, который я напечатал. Второе событие имеет pdwChange, равное 0, но имя задания на печать, указанное в notifyInfo, является именем файла, которое я использовал для печати. Поскольку я использую FreePDF для тестирования pruproses, я думаю, что первое событие принтера является чем-то внутренним для моей специальной настройки.
Уведомления об удалении задания на печать также создают 0 событий. На этот раз они отправляются до того, как FindNextPrinterChangeNotification возвращает 1024 в pdwChange, и своевременно очень близко после начала задания печати. В этом случае ровно одно сгенерированное событие 0 содержит notifyInfo с именем документа, равным имени файла, который я начал печатать. После события 0 есть ровно одно дополнительное событие с pdwChange, равным 1024, но без каких-либо данных для notifyInfo.
Я думаю, что Windows использует некоторый механизм, который предоставляет дополнительные уведомления для того же события, что и 0 событий после того, как начальное событие было запущено, с его реальной стоимостью, с которой уведомил пользователь, например, 256 для PRINTER_CHANGE_ADD_JOB. С другой стороны, кажется, что некоторые 0 событий просто запускаются, чтобы предоставить данные для предстоящего события, которое затем получает реальное значение, например 1024 для PRINTER_CHANGE_DELETE_JOB, но без дополнительных данных, поскольку они уже были доставлены потребителю события с очень ранним 0 событием. Что-то вроде «Смотри, есть еще что-то для последних событий». и «Посмотрите, что-то произойдет с данными, которые я уже предоставляю сейчас». Внедряя такой подход, мои отпечатки теперь работают, как и ожидалось.
Конечно, то, что я написал, не соответствует тому, что задокументировано для FindNextPrinterChangeNotification, но для меня это имеет смысл. 😉
Вы не проверяете наличие переполнений или ошибок.
Документация для FindNextPrinterChangeNotification говорит это:
Если бит члена PRINTER_NOTIFY_INFO_DISCARDED установлен в элементе Flags
структура PRINTER_NOTIFY_INFO, переполнение или ошибка, и
уведомления могут быть потеряны. В этом случае никаких дополнительных
уведомления будут отправляться, пока вы не сделаете второй
Вызов FindNextPrinterChangeNotification, который указывает
PRINTER_NOTIFY_OPTIONS_REFRESH.
Вы должны проверить этот флаг и сделать, как описано выше, а также вы должны проверить код возврата из FindNextPrinterChangeNotification
,