Client-Side UI Automation Provider - WinForm Sample
2014-09-15
引用程序集[1]
- UIAutomationClient.dll
- UIAutomationProviders.dll
- UIAutomationTypes.dll
实现提供程序接口[2]
以下示列实现提供程序接口:IRawElementProviderSimple
1 class WindowProvider : IRawElementProviderSimple 2 { 3 IntPtr providerHwnd; 4 public WindowProvider(IntPtr hwnd) 5 { 6 providerHwnd = hwnd; 7 } 8 internal static IRawElementProviderSimple Create( 9 IntPtr hwnd, int idChild, int idObject) 10 { 11 System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("WinFormServer"); 12 if (processes.Length == 0) 13 return null; 14 //Check if the target is specified process 15 //If yes, create and run provider instance 16 if (processes[0].MainWindowHandle != hwnd) 17 return null; 18 else 19 return new WindowProvider(hwnd); 20 } 21 ProviderOptions IRawElementProviderSimple.ProviderOptions 22 { 23 get 24 { 25 //Return ClientSideProvider as the implementation is in client 26 return ProviderOptions.ClientSideProvider; 27 } 28 } 29 IRawElementProviderSimple IRawElementProviderSimple.HostRawElementProvider 30 { 31 get 32 { 33 return AutomationInteropProvider.HostProviderFromHandle(providerHwnd); 34 } 35 } 36 object IRawElementProviderSimple.GetPropertyValue(int aid) 37 { 38 if (AutomationProperty.LookupById(aid) == 39 AutomationElementIdentifiers.NameProperty) 40 { 41 //Our UIA.Name property implementation 42 //In production code, usually it uses Win32 or MSAA to get real information 43 return "UIA Client Implementation"; 44 } 45 else 46 { 47 return null; 48 } 49 } 50 object IRawElementProviderSimple.GetPatternProvider(int iid) 51 { 52 //Return null means it does not support any Pattern Provider 53 return null; 54 } 55 }
分发客户端提供程序[1][2]
UI 自动化应在托管代码程序集中查找客户端提供程序。该程序集中的命名空间应与该程序集同名。例如,称为UIAClientProvider.dll 的程序集应包含UIAClientProvider命名空间。 在该命名空间内创建 UIAutomationClientSideProviders 类。 在静态 ClientSideProviderDescriptionTable 字段的实现中,创建用于描述该提供程序的 ClientSideProviderDescription 结构数组。
ClientSideProviderDescription 结构数组将指定以下属性:
- 一个回调函数,用于创建提供程序对象。
- 提供程序支持的控件的类名。
- 提供程序支持的应用程序的映像名(通常是可执行文件的全名)。
- 控制如何根据目标应用程序中的窗口类对类名进行匹配的标志。
最后两个参数是可选的。 如果客户端希望对不同的应用程序使用不同的提供程序,则可以指定目标应用程序的映像名。 例如,客户端可以对支持多视图模式的已知应用程序中的 Win32 列表视图控件使用一个提供程序,而对不支持多视图模式的另一个已知应用程序中的类似控件使用另一个提供程序
1 class UIAutomationClientSideProviders 2 { 3 public static ClientSideProviderDescription[] ClientSideProviderDescriptionTable = 4 { new ClientSideProviderDescription( 5 WindowProvider.Create, 6 null) }; 7 }
注册和配置客户端提供程序[1][2]
动态链接库 (DLL) 中的客户端提供程序通过调用 RegisterClientSideProviderAssembly 进行加载。 无需进一步的操作,客户端应用程序便可以使用这些提供程序。
在客户端自己的代码中实现的提供程序通过使用 RegisterClientSideProviders 进行注册。 此方法将 ClientSideProviderDescription 结构数组用作参数。
ClientSettings.RegisterClientSideProviders(UIAutomationClientSideProviders.ClientSideProviderDescriptionTable);
WinForm Sample[2]
创建Console Application:UIAClientProvider,代码如下:
1 using System; 2 using System.Windows.Automation.Provider; 3 using System.Windows.Automation; 4 5 namespace UIAClientProvider 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 ClientProviderSample.ClientProviderTest(); 12 } 13 } 14 15 public class ClientProviderSample 16 { 17 public static void ClientProviderTest() 18 { 19 //Calling RegisterClientSideProviders API to register out Client provider 20 //Client Provider’s type information is stored in ClientSideProviderDescriptionTable Array 21 ClientSettings.RegisterClientSideProviders(UIAutomationClientSideProviders.ClientSideProviderDescriptionTable); 22 //Obtain main window of test target 23 System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("WinFormServer"); 24 if (processes.Length == 0) 25 return; 26 IntPtr hwnd = processes[0].MainWindowHandle; 27 //Get UIA object of the test target main window 28 AutomationElement elementWindow = AutomationElement.FromHandle(hwnd); 29 //Read UIA.Name property 30 Console.WriteLine(elementWindow.Current.Name); 31 Console.WriteLine(); 32 Console.WriteLine("Press any key to exit."); 33 Console.ReadLine(); 34 } 35 } 36 class UIAutomationClientSideProviders 37 { 38 public static ClientSideProviderDescription[] ClientSideProviderDescriptionTable = 39 { new ClientSideProviderDescription( 40 WindowProvider.Create, 41 null) }; 42 } 43 class WindowProvider : IRawElementProviderSimple 44 { 45 IntPtr providerHwnd; 46 public WindowProvider(IntPtr hwnd) 47 { 48 providerHwnd = hwnd; 49 } 50 internal static IRawElementProviderSimple Create( 51 IntPtr hwnd, int idChild, int idObject) 52 { 53 System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("WinFormServer"); 54 if (processes.Length == 0) 55 return null; 56 //Check if the target is specified process 57 //If yes, create and run provider instance 58 if (processes[0].MainWindowHandle != hwnd) 59 return null; 60 else 61 return new WindowProvider(hwnd); 62 } 63 ProviderOptions IRawElementProviderSimple.ProviderOptions 64 { 65 get 66 { 67 //Return ClientSideProvider as the implementation is in client 68 return ProviderOptions.ClientSideProvider; 69 } 70 } 71 IRawElementProviderSimple IRawElementProviderSimple.HostRawElementProvider 72 { 73 get 74 { 75 return AutomationInteropProvider.HostProviderFromHandle(providerHwnd); 76 } 77 } 78 object IRawElementProviderSimple.GetPropertyValue(int aid) 79 { 80 if (AutomationProperty.LookupById(aid) == 81 AutomationElementIdentifiers.NameProperty) 82 { 83 //Our UIA.Name property implementation 84 //In production code, usually it uses Win32 or MSAA to get real information 85 return "UIA Client Implementation"; 86 } 87 else 88 { 89 return null; 90 } 91 } 92 object IRawElementProviderSimple.GetPatternProvider(int iid) 93 { 94 //Return null means it does not support any Pattern Provider 95 return null; 96 } 97 } 98 }
创建一个简单的WinForm Application: WinFormServer,代码如下:
1 using System; 2 using System.Windows.Forms; 3 4 namespace WinFormServer 5 { 6 public partial class Form1 : Form 7 { 8 public Form1() 9 { 10 InitializeComponent(); 11 12 this.Name = "testForm"; 13 this.Text = "ClientUIADemo"; 14 15 } 16 } 17 }
操作:
打开WinFormServer.exe。
运行UIAClientProvider。