调用UIAutomation GetTopLevelWindowByName时程序崩溃如何解决
崩溃原因
你代码中声明的CComPtr<IUIAutomation> g_pAutomation仅完成了定义,没有进行初始化操作,此时它是一个空指针。调用g_pAutomation->GetRootElement时触发了ATL智能指针的空指针断言,就会抛出你遇到的p!=0错误。
修复方案
- 第一步:首先需要初始化当前线程的COM环境,UI Automation依赖COM运行时
- 第二步:创建
IUIAutomation接口的实例,给g_pAutomation赋值 - 第三步:检查所有COM调用的返回值,避免空指针操作
修正后的参考代码如下:
// 首先在程序入口处初始化COM环境,比如WinMain或者main函数开头 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // 修正后的GetTopLevelWindowByName实现 IUIAutomationElement* GetTopLevelWindowByName(LPWSTR windowName) { if (windowName == NULL) return NULL; CComPtr<IUIAutomation> g_pAutomation; // 新增:创建IUIAutomation实例 HRESULT hr = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, (void**)&g_pAutomation); if (FAILED(hr) || !g_pAutomation) return NULL; VARIANT varProp; varProp.vt = VT_BSTR; varProp.bstrVal = SysAllocString(windowName); if (varProp.bstrVal == NULL) return NULL; IUIAutomationElement* pRoot = NULL; IUIAutomationElement* pFound = NULL; IUIAutomationCondition* pCondition = NULL; // 获取桌面元素 hr = g_pAutomation->GetRootElement(&pRoot); if (FAILED(hr) || pRoot == NULL) goto cleanup; // 按名称查找顶层元素,例如“Program Manager” hr = g_pAutomation->CreatePropertyCondition(UIA_NamePropertyId, varProp, &pCondition); if (FAILED(hr)) goto cleanup; pRoot->FindFirst(TreeScope_Children, pCondition, &pFound); cleanup: if (pRoot != NULL) pRoot->Release(); if (pCondition != NULL) pCondition->Release(); VariantClear(&varProp); return pFound; } // 程序退出前调用CoUninitialize释放COM环境 // CoUninitialize();
后续遍历UI元素的实现
拿到目标窗口的IUIAutomationElement指针后,调用FindAll方法,传入TreeScope_Descendants作为遍历范围,再搭配对应的属性过滤条件,就能遍历窗口下所有符合要求的UI元素,读取它们的名称、控件类型、描述等属性。
内容的提问来源于stack exchange,提问作者user16839617
相关产品推荐
相关产品推荐

