我遇到了问题,我想寻求帮助:
我的任务是使用带有“打印”动词的 ShellExecuteEx 打印一些不同类型的文件,并且需要保证所有文件的打印顺序。因此,我使用 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 打印一个简单的文本文件,我只会得到一个创建打印作业的事件,pdwChange 的值为 256,我需要在 notifyInfo 中比较我打印的文件名和比较两者的数据。如果我使用当前的 Acrobat Reader 11 打印 pdf 文件,我会收到两个事件,一个事件的 pdwChange 为 256,但给出类似“本地打印数据文件”的内容作为打印作业的名称,这显然不是我打印的文件。第二个事件的pdwChange为0,但是notifyInfo中提供的打印作业名称是我用来打印的文件名。当我使用 FreePDF 测试 pruproses 时,我认为第一个打印机事件是我特殊设置的内部事件。
删除打印作业的通知也创建了 0 个事件。这次是在 FindNextPrinterChangeNotification 在 pdwChange 中返回 1024 之前发送的,并且在打印作业开始后非常及时。在这种情况下,恰好一个生成的 0 事件包含 notifyInfo,其文档名称等于我开始打印的文件名称。在 0 事件之后,正好有一个 pdwChange 为 1024 的附加事件,但没有任何 notifyInfo 数据。
我认为 Windows 正在使用某种机制,该机制在初始事件被触发后为与 0 事件相同的事件提供额外的通知,并且它是用户通知的真实值,例如PRINTER_CHANGE_ADD_JOB 为 256。另一方面,似乎只是触发了一些 0 事件来为即将发生的事件提供数据,然后获得例如的真实值(value)。 PRINTER_CHANGE_DELETE_JOB 为 1024,但不再有数据,因为它已经通过非常早的 0 事件传递给事件消费者。诸如“看,最后的事件还有更多”之类的东西。和“看,我现在已经提供的数据会发生一些事情。”实现这种方法后,我的打印品现在似乎可以按预期工作。
当然,我写的内容与为 FindNextPrinterChangeNotification 记录的内容不符,但它对我来说有点意义。 ;-)
关于c++ - FindNextPrinterChangeNotification 为 ppPrinterNotifyInfo 返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16283827/