如何在 C# 中使用 IUIAutomation::ElementFromIAccessible 方法?

How to use IUIAutomation::ElementFromIAccessible method in C#?

我尝试通过以下方式使用 ElementFromIAccessible 方法:

 System.Windows.Automation;
 ...
 [DllImport("UIAutomationClient.dll")]
    public static extern int ElementFromIAccessible(
        IAccessible accessible,
        int childId,
        [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref AutomationElement element);

其中 AutomationElement 来自 System.Windows.Automation.

当我尝试这样称呼它时:

 Win32.ElementFromIAccessible(this.Accessible, 0, ref automaitonElement);

失败

"System.Runtime.InteropServices.MarshalDirectiveException" "Unable to pack parameter #3"

如何正确映射它?

TL; DR; 本质上它失败了,因为您正在尝试 p-invoke 一个不存在的本机方法,并且您正在尝试在 COM 库上使用 p-invoke。无论如何,COM 不会(除了 DllRegisterServerDllRegisterServer)在 DLL 的导出 table 中列出 class 方法。在UIAutomationClient.dll中没有ElementFromIAccessible()这样的函数。但是有一个接口成员。

How to use IUIAutomation::ElementFromIAccessible method in C#?

IUIAutomation 等是 COM 类型,因此您不应该 使用 p-invoke。相反,您应该使用 COM 互操作。

首先,在您的项目中添加对 UIAutomationClient v1.0 的 COM 引用:

然后,使用如下代码,您为 CUIAutomation 创建一个实例并调用 IUIAutomation.ElementFromIAccessible() 方法:

CUIAutomation automation = new CUIAutomation();
IAccessible accessible = // you need to supply a value here
int childId = 0; // you need to supply a value here
IUIAutomationElement element = automation.ElementFromIAccessible(accessible, childId);

How Do I map it right way?

您不能将 IUIAutomationElement 转换为 System.Windows.Automation 中的类型,因为:

  1. 一个是 COM 类型,另一个是托管类型
  2. IUIAutomationElement 未在 System.Windows.Automation
  3. 中定义
  4. System.Windows.Automation.AutomationElement没有实现IUIAutomationElement(后者反正是COM类型)

你应该只使用 COM UIA,不要混合和匹配。此外,根据 doco,COM UIA 比托管库具有更多功能。

动态

您可以通过 IDispatch 使用 .NET 4 的动态 COM 对象调用功能,例如:

dynamic element = automation.ElementFromIAccessible (...);
string name = element.accName;

...但是自动完成将不起作用。由于您已经可以通过提供强类型的 COM 参考访问 UIA 类型库,因此这种替代方法的用处不大。