Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

I've tried to use ElementFromIAccessible method via:

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

where AutomationElement is from System.Windows.Automation.

And when I try to call it like:

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

It fails with

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

How Do I map it right way?

like image 871
Viktor Sidochenko Avatar asked Jul 06 '16 06:07

Viktor Sidochenko


1 Answers

TL; DR; essentially it's failing because you are trying to p-invoke a non-existent native method and also that you are trying to use p-invoke on a COM library. COM does not (apart from DllRegisterServer and DllRegisterServer) list class methods in the DLL's export table anyway. There is no such function called ElementFromIAccessible() in UIAutomationClient.dll. However there is a interface member.

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

IUIAutomation and the like are COM types so you should not be using p-invoke. Instead you should be using COM interop.

First, in your project add a COM reference to UIAutomationClient v1.0:

enter image description here

Then, using code like the following, you create an instance to CUIAutomation and invoke the IUIAutomation.ElementFromIAccessible() method:

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?

You can't cast IUIAutomationElement to types in System.Windows.Automation because:

  1. One is a COM type and the other is managed
  2. IUIAutomationElement is not defined in System.Windows.Automation
  3. System.Windows.Automation.AutomationElement does not realise IUIAutomationElement (the latter is a COM type anyway)

You should just use the COM UIA and refrain from mixing and matching. Also, according to the doco, COM UIA has more features than the managed library.

Dynamic

You could use .NET 4's features of dynamic COM object invokation using IDispatch like:

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

...however auto-complete won't work. Since you already have access to UIA type library via the COM Reference which does provide strong typing, such an alternative is somewhat less useful.

like image 181
MickyD Avatar answered Sep 28 '22 02:09

MickyD