c++ - FindNextPrinterChangeNotification 为 ppPrinterNotifyInfo 返回 NULL

标签 c++ c winapi printing print-spooler-api

我遇到了问题,我想寻求帮助:

我的任务是使用带有“打印”动词的 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*) &notifyInfo);
    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/

相关文章:

c++ - 可以用 Pimpl 包裹 boost socket 吗?

python - 'for loop' 是一个函数吗?

c - 如何从编译后的代码中获取c源代码

c++ - 从内存转储中找出线程消息队列中的消息计数

c++ - 检查文件是否在 C++ 中是只读的

c++ - Qt错误涉及清洁项目未修复的MOC文件

c++ - 此错误发生在 : Exception thrown at 0x0F2BFB7C (ucrtbased. dll) 是试图更改大小的问题吗?

c++ - 为什么 std::atomic_ref 没有根据 std::atomic 实现

c编程scanf

c++ - 服务器在监听客户端连接时是否阻止执行?