FindNextPrinterChangeNotification对于ppPrinterNotifyInfo返回NULL
FindNextPrinterChangeNotification returns NULL for ppPrinterNotifyInfo
我被问题卡住了,我想寻求一些帮助:
我的任务是使用带有"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中获得任何附加数据。这适用于start事件,不过,我使用日志和调试器进行了验证。但是对于PRINTER_CHANGE_DELETE_JOB,我得到的唯一东西是NULL。
我已经在网上搜索过了,有一些类似的问题,但大多数时间都与VB有关,或者只是没有答案。我正在使用一个c++项目,因为我的代码为ADD_JOB-event工作,我不认为我做了什么完全错误的事情。但即使是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,但打印作业启动的名称类似于"local printdatafile",这显然不是我打印的文件。第二个事件的pdwChange为0,但是notifyInfo中提供的打印作业的名称是我用来打印的文件名。当我使用FreePDF来测试程序时,我认为第一个打印机事件是我特殊设置的内部事件。
删除打印作业的通知也会创建0个事件。这一次,它们在FindNextPrinterChangeNotification在pdwChange中返回1024之前发送,并且在打印作业开始之后及时发送。在本例中,生成的0事件包含notifyInfo,其文档名称等于我开始打印的文件名。在0事件之后,正好有一个pdwChange为1024的额外事件,但是没有notifyInfo的任何数据。
我认为Windows正在使用一些机制,在初始事件被触发后,为相同的事件提供额外的通知,并使用用户通知的实际值,例如PRINTER_CHANGE_ADD_JOB的256。另一方面,似乎一些0事件只是简单地为即将到来的事件提供数据,然后获得真实值,例如PRINTER_CHANGE_DELETE_JOB的1024,但没有更多的数据,因为已经通过非常早的0事件交付给事件消费者。比如"看,最后的事件还有更多"answers"看,我现在已经提供的数据将会发生一些事情。"实现了这样的方法,我的印刷品现在似乎像预期的那样工作了。
当然我写的不适合什么是FindNextPrinterChangeNotification的文档,但它对我来说有点意义。: -)
您没有检查溢出或错误。
FindNextPrinterChangeNotification的文档是这样说的:
PRINTER_NOTIFY_INFO_DISCARDED的Flags成员位PRINTER_NOTIFY_INFO结构,发生溢出或错误,并且通知可能已经丢失。在本例中,没有额外的通知将被发送,直到你做出第二个选择FindNextPrinterChangeNotification调用,指定PRINTER_NOTIFY_OPTIONS_REFRESH .
您需要检查该标志并执行上述操作,并且您还应该检查来自FindNextPrinterChangeNotification
的返回代码。
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 如何在映射中返回null
- 为什么返回 NULL 不会破坏函数?
- fopen 在 gdb 中返回 NULL
- 为什么要从main()返回NULL?
- 为什么TinyXML2的XMLDocument::FirstChild()函数在尝试解析这个有效的XML文件时返回NULL?
- Box2D World.GetBodyList() 返回 NULL,但 World 显然正在更新对象
- API 返回智能指针的 std::optional 以明确指定指针可能为 null 是否有意义?
- boost::p ython:PyErr_Fetch始终返回 NULL 回溯
- 如何在 Visual C++ 中从返回类型为 map 的函数返回 null?
- 如何在C++中返回Null作为引用
- 从模板化函数返回Null对象
- 如何返回值为NULL的变量指针
- Windows 函数"GetCursorInfo"返回成功,但光标的句柄为 NULL
- GDALOpen 在 GEOTiff 文件上返回 null
- 将对象作为 null 返回内容
- QList<float* 类型的 NULL 返回值>
- 在用C++编写的COM客户端中引发异常的Null返回值
- nullptr初始值和WinAPI NULL返回
- DirectX pEnum->Next(1,&pPin,NULL) 返回S_FALSE