是否可以检测到哪些应用程序正在使用类似于 FRAPS 的 OpenGL 或 DirectX?(可能使用某种形式的钩子)?我可能不需要实际绘制到窗口,我只需要知道哪些进程目前正在执行某种形式的 3D 渲染。
(编辑:)如果您不熟悉它,FRAPS 是一个可用于在 3D 应用程序上绘制“每秒帧数”计数器的程序。FRAPS 会自行查找所有正在运行的 3D 应用程序,而无需您指定进程名称。
绘制到外部游戏的“每秒帧数”计数器示例:
可能最简单的方法是检查 OpenGL 和 DirectX 核心库的存在,也可能是添加驱动程序 OGL dll 的好主意(例如 nvogl),这可以通过EnumProcesses
&EnumProcessModulesEx
使用 p/invoke 来完成,这至少会为您提供一组可能使用 OGL 或 DX 的初始流程。
当然,有些应用程序同时加载两个 API 并仅使用一个,或者仅有条件地使用 GFX API 之一(尽管后者仅使用专用工具等发生),为此,IMO,最好的检查方法是执行某种形式的注入或像调试器一样附加到进程,然后挂钩Present
DX 或wglSwapBuffers
OGL。
您可能会通过枚举 GDI 句柄并查找 DXGI 或 OGL 渲染上下文来避免不使用钩子,我不知道这有多可行。
据我了解,FRAPS 使用相对蛮力的方法来确定在哪里开店。该进程从 SetWindowsHookEx 开始,以请求操作系统将 FRAPS 挂钩 DLL 加载到它可以 [和未来进程] 的每个正在运行的进程中。DLL 中的神奇之处在于使用 GetModuleHandleA 运行一组程序测试,以观察它所连接的进程是否已加载任何 OpenGL/DirectX 模块。如果所有调用都返回 NULL,则挂钩会尝试将自身从进程中删除。
另一方面,如果进程已加载它们,它只需通过移除保护并注入 JMP 挂钩来从该库中挂钩适当的渲染函数。wglSwapBuffers 通常是 OpenGL 中唯一相关的。当进程调用此函数时,它最终调用 FRAPS 模块,然后 FRAPS 将后台缓冲区捕获到其队列中以编码为 AVI 并呈现其少量指示。然后它处理对 wglSwapBuffers 的原始请求并将执行返回给程序。
至于在 C# 中查询...查看 EasyHook (http://easyhook.codeplex.com/),看看它是否不适合您。我个人对这个 API 没有经验。
您应该看看如何在 Windows 游戏上叠加图形?和链接的文章http://www.ring3circus.com/gameprogramming/case-study-fraps/。
第二个链接有一些概念代码应该做实际的钩子部分。它还详细介绍了我想复制和粘贴到这个答案中的方式和原因。