TL;DR:我做错了什么导致工作区窗格显示在检查对象中但不显示在我的自定义代码中?
我正在尝试向第三方程序编写一些 UI 自动化。我正在使用 Windows SDK 附带的 Inspect.exe,并且我尝试了 System.Windows.Automation 和直接 COM 调用(使用来自 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);
我将得到返回的正确元素。我可以使用它作为一种解决方法,因为文档窗口是我真正想要的窗口,但我想知道为什么工作区窗格不会显示,这样我可以提高我的技能,以防将来遇到这种情况我无法解决这种情况。
更新:我尝试了戈麦斯先生的建议
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);
工作区元素仍然为空。
我终于让工作区出现了,但我必须执行
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 ]
非常好的问题。根据您记录的问题,很明显您的条件:
PropertyCondition workspaceCond = new PropertyCondition(
AutomationElement.NameProperty, "Workspace", PropertyConditionFlags.IgnoreCase);
...评估失败。为什么?
答案是如何评估你的条件。查看您的元素树,我们注意到
Workspace
: 的此属性
IsWindowPatternAvailable: false
对于主窗口和
Untitled3
:
IsWindowPatternAvailable: true
UIA_IsWindowPatternAvailablePropertyId 30044
标识
属性,该属性指示窗口控制模式是否可用于自动化元素。如果IsWindowPatternAvailable
,客户端可以从元素检索TRUE
接口。IUIAutomationWindowPattern
我们在此线程中找到了一个重现,这意味着与您当前遇到的故障模式相同。我们还注意到该元素缺少 Window
属性,因为
IUIAutomationWindowPattern
无法访问。可以从
aforelinked thread获得解决方法。除了 PropertyCondition
,人们还可以使用:
public class ConditionMatcher : IMatchConditions
{
public bool Matches(AutomationElement element, Condition condition)
{
return new TreeWalker(condition).Normalize(element) != null;
}
}
或者,也可以使用您给出的解决方法,前提是您的树结构保证是浅的(因此,适合此站点的名称,不会触发堆栈溢出)。诚然,这不是最明显的问题。在完美的世界中,MSDN
应该有关于这个主题的更好的文档。
g_hwd = FindWindowEx(g_hwd,NULL,_T("MDIClient"), _T("Untitled3"));
IUIAutomation* 自动化;
HRESULT hr = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&automation));
如果(失败(小时)){
计算
<< "Failed to create UI Automation instance." << endl;
return;
}
IUIAutomationElement* element;
hr = automation->ElementFromHandle(g_hwd, &element);