我们有一个打印驱动程序,它在驱动程序的 UI 模块中捕获打印 exe 的名称。它通过使用 GetModuleFileName
函数来做到这一点。这在 64 位机器上打印 32 位之前效果很好。在这种情况下,Windows 调用 splwow64.exe 来代表 32 位应用程序进行打印,因此 GetModuleFileName
返回“splwow64.exe”作为打印应用程序,而不是实际进行打印的应用程序。
我们试图通过使用 Toolhelp32 API 捕获 splwow64.exe 的父进程来解决这个问题,但这并不可靠,因为一旦第一个应用程序完成打印以便为其他应用程序提供服务,splwow64 就会保持加载状态。这意味着父进程可能是也可能不是实际打印的进程。到目前为止,我们一直无法找到连接 splwow64 和打印应用程序的任何文件或命名管道或其他 IPC 对象。
Microsoft 发布了一个修补程序 (KB2815716),导致 splwow64 在用户指定的超时期限后终止,但这并不能解决问题,因为只要调用它的第一个打印应用程序保持加载状态,splwow64.exe 就会无限期地保留在内存中。它完全忽略了热修复提供的超时。 (我认为这是一个 Windows 错误。)
我的问题是这样的:
我们需要一种方法来可靠地确定正在打印的应用程序恰好是 32 位的并且正在使用 splwow64.exe。
该解决方案可以驻留在打印驱动程序或用户模式应用程序中——两者都可以。我们强烈建议不要使用涉及 API Hook 或代码注入(inject)的技术,因为这些操作往往会被防病毒软件标记。
最佳答案
我从引用的修补程序中假设您的目标是 Vista 之后的机器。
GetPrintExecutionData
函数旨在提供您想要的信息。它确实假设您在后台处理程序的上下文中运行,但从问题来看,这似乎不是问题。该函数返回一个带有成员的 PRINT_EXECUTION_DATA
结构
KB2815716 中提到的问题可能仍会影响此。我假设 KB 安装已经过验证,并且超时是默认值(2 分钟)或非零。对于请求打印的进程是否必须终止,或者打印作业是否必须终止,KB 有点含糊不清。此外,如果终端服务以任何方式与打印有关,如在 KB2513330
中,那么您可能需要设置 Sysprocs
键。
关于winapi - 涉及splwow64.exe时如何检测打印应用程序?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32320005/