【问题标题】:AutomationElement shows up using Inspect.exe but does show not up when using UIAutomationCore.dll or System.Windows.AutomationAutomationElement 使用 Inspect.exe 显示,但在使用 UIAutomationCore.dll 或 System.Windows.Automation 时不显示
【发布时间】:2012-03-06 03:20:10
【问题描述】:

TL;DR:我做错了什么导致工作区窗格显示在检查对象中但未显示在我的自定义代码中?


我正在尝试为第 3 方程序编写一些 UI 自动化。我正在使用Windows SDK 附带的Inspect.exe,我已经尝试过System.Windows.Automation 和直接COM Calls(使用来自UIA Verify 的包装库)。

Process[] processes = Process.GetProcessesByName("Redacted Client");
if (processes.Length == 0) throw new Exception("Could not find \"Redacted Client\" process");

PropertyCondition parentFileCond = new PropertyCondition(AutomationElement.ProcessIdProperty, processes[0].Id);
PropertyCondition workspaceCond = new PropertyCondition(AutomationElement.NameProperty, "Workspace", PropertyConditionFlags.IgnoreCase);
PropertyCondition documentCond = new PropertyCondition(AutomationElement.NameProperty, "Untitled3", PropertyConditionFlags.IgnoreCase);

var parentElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, parentFileCond);
var workspaceElement = parentElement.FindFirst(TreeScope.Children, workspaceCond); //Also does not work with TreeScope.Descendants
var documentElement = workspaceElement.FindFirst(TreeScope.Children, documentCond);

当我尝试上面的代码时,parentElement 确实有对主程序窗口的正确引用,但workspaceElement 为空。


临时解决方法:

如果我将documentElement 代码更改为:

var documentElement = parentElement.FindFirst(TreeScope.Descendants, documentCond);

我会返回正确的元素。我可以将其用作一种解决方法,因为无论如何文档窗口都是我真正想要的,但我想知道为什么工作区窗格不会显示,这样我就可以提高我的技能,以防将来遇到这种情况我无法解决的情况。


更新:我尝试了 MrGomez 的建议

PropertyCondition parentFileCond = new PropertyCondition(AutomationElement.ProcessIdProperty, 5872);
PropertyCondition panelCond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane);

var parentElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, parentFileCond);
var panels = parentElement.FindAll(TreeScope.Children, panelCond);

我得到 3 个结果,不幸的是,我有 4 个面板,其中一个没有显示的是名为 Workspace 的面板。

我也尝试使用TreeWalker

PropertyCondition parentFileCond = new PropertyCondition(AutomationElement.ProcessIdProperty, 5872);
PropertyCondition workspaceCond= new PropertyCondition(AutomationElement.NameProperty, "Workspace");

var walker = new TreeWalker(workspaceCond);
var parentElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, parentFileCond);
var workspaceElement = walker.Normalize(parentElement);

但这也为workspaceElement返回null

最后,无奈之下,我尝试了 Inspect 中“NativeWindowHandle”的当前值,并从根节点开始行走。

PropertyCondition workspaceCond = new PropertyCondition(AutomationElement.NativeWindowHandleProperty, 0x110906);
var walker = new TreeWalker(workspaceCond);
var workspaceElement = walker.Normalize(AutomationElement.RootElement);

工作区元素 STILL 为空。


找到结果

我终于让 Workspace 出现了,但我必须执行

PropertyCondition workspaceCond = new PropertyCondition(AutomationElement.NativeWindowHandleProperty, 0x110906);
var test = AutomationElement.RootElement.FindFirst(TreeScope.Subtree, workspaceCond); 

而且运行需要相当长的时间。

旧屏幕截图

这是来自 Inspect.exe 的屏幕截图,显示了树状视图。

这里是程序主窗口的属性。

How found:  Selected from tree...
RuntimeId:  "[42.2557552]"
BoundingRectangle:  {l:75 t:1 r:1311 b:1003}
ProcessId:  8160
ControlType:    UIA_WindowControlTypeId (0xC370)
LocalizedControlType:   "window"
Name:   "Redacted"
AccessKey:  ""
HasKeyboardFocus:   false
IsKeyboardFocusable:    true
IsEnabled:  true
ClassName:  "C:\Program Files (x86)\RedactedProgramFiles7\RedactedClientFolder"
HelpText:   ""
IsPassword: false
NativeWindowHandle: 0x270670
IsOffscreen:    false
FrameworkId:    "Win32"
ProviderDescription:    "[pid:4000,hwnd:0x270670 Main:Nested [pid:8160,hwnd:0x270670 Annotation(parent link):Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main:Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]; Nonclient:Microsoft: Non-Client Proxy (unmanaged:uiautomationcore.dll); Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]"
Window.CanMaximize: true
Window.CanMinimize: true
Window.WindowVisualState:   Normal (0)
Window.WindowInteractionState:  ReadyForUserInteraction (2)
Window.IsModal: false
Window.IsTopmost:   false
Transform.CanMove:  true
Transform.CanResize:    true
Transform.CanRotate:    false
LegacyIAccessible.ChildId:  0
LegacyIAccessible.DefaultAction:    ""
LegacyIAccessible.Description:  ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: "Redacted"
LegacyIAccessible.Role: client (0xA)
LegacyIAccessible.State:    focusable (0x100000)
LegacyIAccessible.Value:    ""
IsDockPatternAvailable: false
IsExpandCollapsePatternAvailable:   false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable:   false
IsLegacyIAccessiblePatternAvailable:    true
IsMultipleViewPatternAvailable: false
IsRangeValuePatternAvailable:   false
IsScrollPatternAvailable:   false
IsScrollItemPatternAvailable:   false
IsSelectionItemPatternAvailable:    false
IsSelectionPatternAvailable:    false
IsTablePatternAvailable:    false
IsTableItemPatternAvailable:    false
IsTextPatternAvailable: false
IsTogglePatternAvailable:   false
IsTransformPatternAvailable:    true
IsValuePatternAvailable:    false
IsWindowPatternAvailable:   true
IsItemContainerPatternAvailable:    false
IsVirtualizedItemPatternAvailable:  false
IsSynchronizedInputPatternAvailable:    false
FirstChild: "Workspace" pane
LastChild:  "Application" menu bar
Next:   "Inspect  (HWND: 0x01700F06)" window
Previous:   "Sandbox Console (Debugging) - Microsoft Visual Studio (Administrator)" window
Other Props:    Object has no additional properties
Children:   "Workspace" pane
    (null) title bar
    "Application" menu bar
Ancestors:  "Desktop" pane
    [ No Parent ]

这里是问题“工作区”窗格的属性。

How found:  Selected from tree...
RuntimeId:  "[42.34146524]"
BoundingRectangle:  {l:83 t:51 r:1303 b:995}
ProcessId:  8160
ControlType:    UIA_PaneControlTypeId (0xC371)
LocalizedControlType:   "pane"
Name:   "Workspace"
AccessKey:  ""
HasKeyboardFocus:   false
IsKeyboardFocusable:    true
IsEnabled:  true
ClassName:  "MDIClient"
HelpText:   ""
IsPassword: false
NativeWindowHandle: 0x20908DC
IsOffscreen:    false
FrameworkId:    "Win32"
ProviderDescription:    "[pid:4000,hwnd:0x20908DC Main:Nested [pid:8160,hwnd:0x20908DC Annotation(parent link):Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main:Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]; Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]"
LegacyIAccessible.ChildId:  0
LegacyIAccessible.DefaultAction:    ""
LegacyIAccessible.Description:  ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: "Workspace"
LegacyIAccessible.Role: client (0xA)
LegacyIAccessible.State:    focusable (0x100000)
LegacyIAccessible.Value:    ""
IsDockPatternAvailable: false
IsExpandCollapsePatternAvailable:   false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable:   false
IsLegacyIAccessiblePatternAvailable:    true
IsMultipleViewPatternAvailable: false
IsRangeValuePatternAvailable:   false
IsScrollPatternAvailable:   false
IsScrollItemPatternAvailable:   false
IsSelectionItemPatternAvailable:    false
IsSelectionPatternAvailable:    false
IsTablePatternAvailable:    false
IsTableItemPatternAvailable:    false
IsTextPatternAvailable: false
IsTogglePatternAvailable:   false
IsTransformPatternAvailable:    false
IsValuePatternAvailable:    false
IsWindowPatternAvailable:   false
IsItemContainerPatternAvailable:    false
IsVirtualizedItemPatternAvailable:  false
IsSynchronizedInputPatternAvailable:    false
FirstChild: "Untitled3" window
LastChild:  "Letters (32638 of 32638):" window
Next:   (null) title bar
Previous:   [null]
Other Props:    Object has no additional properties
Children:   "Untitled3" window
    "Letters (32638 of 32638):" window
Ancestors:  "Redacted" window
    "Desktop" pane
    [ No Parent ]

这里是“工作”文档窗口的属性。

How found:  Selected from tree...
RuntimeId:  "[42.9505096]"
BoundingRectangle:  {l:85 t:53 r:651 b:491}
ProcessId:  8160
ControlType:    UIA_WindowControlTypeId (0xC370)
LocalizedControlType:   "window"
Name:   "Untitled3"
AccessKey:  ""
HasKeyboardFocus:   false
IsKeyboardFocusable:    true
IsEnabled:  true
AutomationId:   "10"
ClassName:  "ProToolsSubMDIWndClass"
HelpText:   ""
IsPassword: false
NativeWindowHandle: 0x910948
IsOffscreen:    false
FrameworkId:    "Win32"
ProviderDescription:    "[pid:4000,hwnd:0x910948 Main:Nested [pid:8160,hwnd:0x910948 Annotation(parent link):Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main:Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]; Nonclient:Microsoft: Non-Client Proxy (unmanaged:uiautomationcore.dll); Hwnd(parent link):Microsoft: HWND Proxy (unmanaged:uiautomationcore.dll)]"
Window.CanMaximize: true
Window.CanMinimize: true
Window.WindowVisualState:   Normal (0)
Window.WindowInteractionState:  ReadyForUserInteraction (2)
Window.IsModal: false
Window.IsTopmost:   false
Transform.CanMove:  true
Transform.CanResize:    true
Transform.CanRotate:    false
LegacyIAccessible.ChildId:  0
LegacyIAccessible.DefaultAction:    ""
LegacyIAccessible.Description:  ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: "Untitled3"
LegacyIAccessible.Role: client (0xA)
LegacyIAccessible.State:    focusable (0x100000)
LegacyIAccessible.Value:    ""
IsDockPatternAvailable: false
IsExpandCollapsePatternAvailable:   false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable:   false
IsLegacyIAccessiblePatternAvailable:    true
IsMultipleViewPatternAvailable: false
IsRangeValuePatternAvailable:   false
IsScrollPatternAvailable:   false
IsScrollItemPatternAvailable:   false
IsSelectionItemPatternAvailable:    false
IsSelectionPatternAvailable:    false
IsTablePatternAvailable:    false
IsTableItemPatternAvailable:    false
IsTextPatternAvailable: false
IsTogglePatternAvailable:   false
IsTransformPatternAvailable:    true
IsValuePatternAvailable:    false
IsWindowPatternAvailable:   true
IsItemContainerPatternAvailable:    false
IsVirtualizedItemPatternAvailable:  false
IsSynchronizedInputPatternAvailable:    false
FirstChild: "" thumb
LastChild:  (null) title bar
Next:   "Letters (32638 of 32638):" window
Previous:   [null]
Other Props:    Object has no additional properties
Children:   "" thumb
    (null) title bar
Ancestors:  "Workspace" pane
    "Redacted" window
    "Desktop" pane
    [ No Parent ]

【问题讨论】:

  • Nit:我猜你在上面的评论中是指TreeScope.Descendants
  • 帮我一个忙,因为您的 IDE 中有此代码?在您的工作区窗格上快速发送autoElement.GetCurrentPropertyValue(AutomationElement.NameProperty, true),看看它会带来什么。如果这正确返回“工作区”,则显然有其他问题。
  • 我们可以通过查看PropertyCondition workspaceCond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane); 在针对您的树进行评估时是否返回非空值来进一步完善这一点。如果这更正了遍历,那么诀窍就是找出你的 name 属性没有正确评估的原因。从粗略的文档分析来看,您的代码应该可以正常工作,但显然不行。
  • 这将是一些,因为我在软件中运行了一个长时间运行的进程(我试图自动化的一件事是,所以我不需要照顾必须关闭的错误对话框让程序在此操作期间继续运行,可能会随机弹出)。完成后,我将更新我的问题。
  • @MrGomez 我有机会对其进行测试,ropertyCondition workspaceCond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane); 返回 null,而且您在回答中的TreeWalker 建议也不起作用(但它让我摆脱了其他的 LINQ 查询工作的部分,谢谢)。我确实通过在根节点下搜索 all 节点来显示它,但这不适用于实际使用。有关详细信息,请参阅我更新的问题。

标签: c# .net automation ui-automation


【解决方案1】:

非常好的问题。根据您记录的问题,很明显您的条件:

PropertyCondition workspaceCond = new PropertyCondition(
 AutomationElement.NameProperty, "Workspace", PropertyConditionFlags.IgnoreCase);

... 评估失败。为什么?

答案是如何评估您的条件。查看您的元素树,我们注意到Workspace 的此属性:

IsWindowPatternAvailable:   false

对于主窗口和Untitled3

IsWindowPatternAvailable:   true

From MSDN:

UIA_IsWindowPatternAvailablePropertyId 30044

标识IsWindowPatternAvailable 属性,该属性指示窗口控件模式是否可用于自动化元素。如果TRUE,客户端可以从元素中检索IUIAutomationWindowPattern接口。

我们找到了一个重现 in this thread,这意味着与您当前遇到的故障模式相同。我们还注意到此元素缺少Window 属性,因为IUIAutomationWindowPattern 不可访问。

可从aforelinked thread 获得解决方法。而不是PropertyCondition,可以使用:

public class ConditionMatcher : IMatchConditions
{
    public bool Matches(AutomationElement element, Condition condition)
    {
        return new TreeWalker(condition).Normalize(element) != null;
    }
}

或者,或者,可以使用您提供的解决方法,前提是您的树结构保证是浅的(因此,适合此站点的名称,不会触发堆栈溢出)。

诚然,这不是最明显的问题。在完美的世界中,MSDN 应该有关于这个主题的更好的文档。

【讨论】:

  • 哇,谢谢!它仍然在执行之前的导出操作(完成之前需要几个小时),但是一旦我可以重新创建情况并对其进行测试,我将对此进行测试。
  • @ScottChamberlain 没问题!目前尚不清楚遍历是否因IUIAutomationWindowPattern 的不可访问性而完全阻塞,但这是最合理的回归。如果情况并非如此,我相信我们有足够多的测试用例来解决这个问题,直到我们找到根本原因。
  • TreeWalker 也不起作用。如果我搜索根节点下的所有节点并查找窗口句柄,我确实会显示它。但这不适用于 Live 使用。
  • 我没有时间工作,忙于其他事情,但赏金即将到期,您在旅途中帮助了我很多,所以我把功劳归功于您。
  • @ScottChamberlain 够公平的!如果您有其他问题,请告诉我。即使没有代表权,我总是很乐意提供帮助。 :)
猜你喜欢
  • 2014-08-04
  • 2021-08-24
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
相关资源
最近更新 更多