You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Inspect.exe可识别UIAutomation无法找到的Qt/C++程序子窗口问题

问题分析与解决

1. Inspect是否使用UI Automation?

是的,Inspect.exe支持UI Automation和MSAA(Microsoft Active Accessibility)两种模式。当切换到UI Automation模式时,它直接调用UIAutomationCore.dll的原生COM接口获取控件信息——你的Qt子窗口正是通过UIA的MSAA代理(从Inspect输出的ProviderDescription字段Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)可确认)暴露给UIA的,所以Inspect能正常识别。

2. .NET UI Automation找不到子窗口的原因

你尝试的FindAll和各类TreeWalker无效,大概率是以下原因:

  • .NET的AutomationElement封装对MSAA代理元素存在默认过滤,非标准控件可能被排除
  • 你获取的elementWindow并非目标子窗口的正确父容器(比如不是Inspect中显示的"ACP RADAR"窗口)
  • Qt子窗口虽被标记为window类型,但未实现UIA的WindowPattern,导致.NET控件视图遍历器将其过滤

3. 解决方法

方法一:确认父窗口的正确性

先确保你定位的elementWindow是目标子窗口的直接父窗口(即Inspect中显示的"ACP RADAR"窗口),可通过进程ID或窗口名称精准定位:

int targetProcessId = 7632; // 替换为你的进程ID
var root = AutomationElement.RootElement;
var mainWindowCondition = new PropertyCondition(
    AutomationElement.ProcessIdProperty, 
    targetProcessId
);
var mainWindow = root.FindFirst(TreeScope.Children, mainWindowCondition);

if (mainWindow != null)
{
    var allElements = mainWindow.FindAll(
        TreeScope.Descendants, 
        Condition.TrueCondition
    );
    // 遍历输出所有元素的名称和类型
    foreach (AutomationElement elem in allElements)
    {
        Console.WriteLine($"{elem.Current.Name} - {elem.Current.LocalizedControlType}");
    }
}

方法二:直接调用UIAutomationCore原生COM接口

绕过.NET封装,直接使用UIAutomationCore的COM接口(这也是Inspect的实现逻辑):

  1. 添加COM引用:
    右键项目 → 添加 → 引用 → COM → 找到Microsoft UI Automation 6.0(对应UIAutomationCore.dll)并添加

  2. 使用COM接口遍历元素:

using UIAutomationClient;

// 复用上面的代码获取目标主窗口的AutomationElement
AutomationElement mainWindow = ...;

// 转换为COM接口元素
var uiAutomation = new CUIAutomation();
IUIAutomationElement comMainWindow = mainWindow.NativeElement as IUIAutomationElement;

// 创建无条件查询,遍历所有后代
IUIAutomationCondition trueCondition = uiAutomation.CreateTrueCondition();
IUIAutomationElementArray elements = comMainWindow.FindAll(
    TreeScope.TreeScope_Descendants, 
    trueCondition
);

// 输出结果
for (int i = 0; i < elements.Length; i++)
{
    IUIAutomationElement elem = elements.GetElement(i);
    Console.WriteLine($"{elem.CurrentName} - {elem.CurrentLocalizedControlType}");
}

这种方式不受.NET封装的过滤限制,能直接获取UIAutomationCore暴露的所有元素。

方法三:自定义无过滤的TreeWalker

如果坚持使用.NET的TreeWalker,可以创建取消所有过滤规则的自定义遍历器:

var customWalker = new TreeWalker(Condition.TrueCondition);
AutomationElement child = customWalker.GetFirstChild(mainWindow);
while (child != null)
{
    Console.WriteLine($"{child.Current.Name} - {child.Current.LocalizedControlType}");
    child = customWalker.GetNextSibling(child);
}

内容的提问来源于stack exchange,提问作者John Kent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:35:40