FindNextPrinterChangeNotification为ppPrinterNotifyInfo返回NULL

如果我想请求帮助,我会遇到问题:

我的任务是使用带有“print”动词的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中获得任何添加数据。 这适用于启动事件,但我使用我的日志和调试器进行了validation。 但是使用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 " <event) <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中我需要的数据,用于比较我的打印文件名和比较两个成功。 如果我使用当前的Acrobat Reader 11打印pdf文件,我会得到两个事件,一个是pdwChange为256,但是提供了类似“本地printdatafile”的内容,因为打印作业的名称已经开始,这显然不是我打印的文件。 第二个事件的pdwChange为0,但notifyInfo中提供的打印作业的名称是我用于打印的文件名。 当我使用FreePDF测试pruproses时,我认为第一个打印机事件是我特殊设置的内部事件。

删除打印作业的通知也会创建0个事件。 这次是在FindNextPrinterChangeNotification在pdwChange中返回1024之前发送的,并且在打印作业开始后及时非常接近。 在这种情况下,正好一个生成的0事件包含notifyInfo,其文档名称等于我开始打印的文件名。 在0事件之后,只有一个附加事件,pdwChange为1024,但没有任何notifyInfo数据。

我认为Windows正在使用一些机制,它在初始事件被触发后为0事件提供相同事件的附加通知,其中包含用户通知的实际值,例如256为PRINTER_CHANGE_ADD_JOB。 另一方面,似乎简单地触发了一些0事件来为即将发生的事件提供数据,然后获得PRINTER_CHANGE_DELETE_JOB的实际值,例如1024,但是没有数据,因为它已经很早就被传递给了事件消费者0事件。 像“看,最后的事件还有更多。” 并且“看,我现在提供的数据会发生一些事情。” 实现这样的方法我的打印现在似乎按预期工作。

当然,我写的内容并不适合FindNextPrinterChangeNotification所记录的内容,但这对我来说有点意义。 😉

您没有检查溢出或错误。

FindNextPrinterChangeNotification的文档说明了这一点:

如果在PRINTER_NOTIFY_INFO结构的Flags成员中设置了PRINTER_NOTIFY_INFO_DISCARDED位,则发生溢出或错误,并且通知可能已丢失。 在这种情况下,在您进行指定PRINTER_NOTIFY_OPTIONS_REFRESH的第二个FindNextPrinterChangeNotification调用之前,不会发送其他通知。

您需要检查该标志并执行上述操作,并且还应检查FindNextPrinterChangeNotification的返回代码。