【发布时间】:2016-07-08 11:52:26
【问题描述】:
背景
我目前正在尝试开发一些测试软件,这些软件需要通知桌面上的窗口创建和激活事件,响应这些并遍历小部件树,以便读取这些窗口上的所有可用文本。这需要在 32 位和 64 位以及 XP 以上的理想情况下工作(叹气),但肯定是 7 以上。
到目前为止我做了什么
我有一个为WH_CBT 消息注册的SetWindowsHookEx() 样式系统挂钩,我专门处理HCBT_ACTIVATE 和HCBT_CREATEWND 事件。挂钩是在 DLL 中完成的,并且有一个挂钩程序来控制它。该程序可用于 32 位和 64 位(因为 HCBT 消息似乎不会被路由回不同架构(32/64 位)的挂钩过程,不像说键盘消息)。该软件全部用非托管C++代码编写,即不依赖CLI,程序是一个控制台应用程序。
当我收到上述两个事件中的任何一个时,我会使用给定的HWND 句柄调用EnumChildWindows(),并在每个窗口上调用GetWindowText()。结果当前根据 PID 写入单个日志文件。
这一切都按预期工作,但仅此而已......
问题
如果我运行说 MSVS,我可以看到顶级内容,甚至“你确定要这样做吗”的文本内容简单的警告对话框,但对于选项对话框,我得到的只是确定和取消窗口小部件和一些未命名的窗口。
阅读这篇文章,我相信原因是我看到了从老式 Win32 API 小部件到 WPF 控件小部件的过渡。
假设/要求
- 这是由于 Win32 到 WPF 的转换。
- 作为从 DLL 注入每个进程的
SetWindowsEx()样式挂钩,这必须是非托管代码(即,您不能在某个随机进程中愉快地启动 CLI 并使用托管代码)。 - WPF 库示例都使用托管代码。
- 据观察,一些应用程序不使用辅助功能 API,因此我不重视这种挂钩。
- 我需要尽可能减少依赖关系,因为被测系统必须尽可能具有代表性(我知道,我在各处注入代码,但这无济于事)。如果可以的话,我不想安装额外的大型运行时等。
- 在测试期间,UAC 将以其默认级别开启。
问题
- 是否有任何方法可以从 DLL 中的非托管 C++ 代码遍历 WPF 小部件层次结构?大概有某种我可以调用的本机/非托管 API?
- 如果不这样做,是否可以将
HWND句柄转发给另一个进程,比如通过WM_COPYDATA和一个隐藏窗口,这实际上是一个托管进程,然后可以代表注入的 DLL 遍历小部件树,访问Win32 小部件,在需要时切换到 WPF?我的研究似乎表明这是不可能的...... - 在 UAC 开启的情况下,进程是否有权执行 (2)?
最后,我应该说,我是一名 Unix/Linux GUI/系统/内核软件工程师,如果以上内容看起来相当基本,请提前道歉,但我无法为这个特定用例找到答案。这也是我的第一个 MS-Windows 程序!
非常感谢,
约翰。
【问题讨论】:
-
UI 自动化(Linux 等效:ATK)会更好地解决您的问题吗?我不完全确定您需要测试什么。
-
您看到的是一个决定使用无窗口控件的应用程序。这是相当普遍的,并且不限于 WPF。所有 Qt 应用程序都使用无窗口控件和大多数浏览器。查看使用 Spy++ 的 Internet Explorer 的窗口层次结构。没什么可看的。你真正需要的是WinEvents 和UI Automation。
标签: c++ windows winapi setwindowshookex