很多网友对于Windows应用程序以及Web应用程序的自动化操作颇感兴趣,在此我给出对应的两份代码,并且附上简要的说明。全文将使用C#.Net 2008来编写代码,对于偏爱VB.Net的用户请自行使用Reflector翻译。
一.Windows Application Automation
本例编码实现自动化操作Windows计算器
1. 启动计算器
2. 输入1+5×8=
3. 验证结果是否等于48 (此计算器不支持先乘除后加减)
代码实现
1. 启动Visual Studio 2008
2. 创建C# Console Application
3. 添加引用UIAutomationClient以及UIAutomationTypes
4. 编码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; using System.Windows.Automation;
namespace CalcManipulate { class Program { static void Main(string[] args) { Process calc = Process.Start("calc"); Console.WriteLine("Launch Windows Calculator"); Thread.Sleep(2000);
AutomationElement e = AutomationElement.FromHandle(calc.MainWindowHandle);
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "125")).Invoke(); Console.WriteLine("Click 1");
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "92")).Invoke(); Console.WriteLine("Click +");
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "129")).Invoke(); Console.WriteLine("Click 5");
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "91")).Invoke(); Console.WriteLine("Click *");
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "132")).Invoke(); Console.WriteLine("Click 8");
e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "112")).Invoke(); Console.WriteLine("Click =");
string result = e.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "403")).GetText(); Console.WriteLine("Result is {0}", result);
if(result == "48") Console.WriteLine("It is correct"); else Console.WriteLine("It is NOT correct"); } }
static class UIAutomation { public static void Invoke(this AutomationElement e) { (e.GetCurrentPattern(InvokePatternIdentifiers.Pattern) as InvokePattern).Invoke(); } public static string GetText(this AutomationElement e) { return (e.GetCurrentPattern(TextPatternIdentifiers.Pattern) as TextPattern).DocumentRange.GetText(-1); } } } |
小结
1. 此例使用AutomationID属性来唯一确定待测程序中的控件位置,如按钮+的AutomationID是92。此属性可以通过Visual Studio来获得
二.Web Application Automation
我们以163邮件服务网站为例,实现自动登录
1. 启动IE
2. 输入http://mail.163.com
3. 输入用户名,密码
4. 点击登录
代码实现
1. 启动Visual Studio 2008
2. 创建C# Console Application,命名为WebMailManipulate
3. 添加引用Microsoft.mshtml、UIAutomationClient以及UIAutomationTypes
4. 编码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; using System.ComponentModel; using System.Windows.Automation;
using mshtml;
namespace WebMailManipulate { class Program { static void Main(string[] args) { Process ie = Process.Start("iexplore", "http://mail.163.com"); Console.WriteLine("Launch http://mail.163.com with PID {0}", ie.Id); Thread.Sleep(5000);
// get ie main window handle AutomationElement e = AutomationElement.FromHandle(ie.MainWindowHandle);
// get ie shell document object view handle e = e.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "Internet Explorer_Server"));
// get document interface from shell document object view handle HTMLDocumentClass document = UIAutomation.GetDomFromShellDocObjectView(e.Current.NativeWindowHandle);
// set user name document.getElementsByName("username").Cast<IHTMLElement>().First().setAttribute("value", "stainboy", 0); Console.WriteLine("Set username to stainboy");
// set password document.getElementsByName("password").Cast<IHTMLElement>().First().setAttribute("value", "111111", 0); Console.WriteLine("Set password to 111111");
// click login button document.getElementsByName("登录邮箱").Cast<IHTMLElement>().First().click(); Console.WriteLine("Click login button"); } }
static class UIAutomation { public static HTMLDocumentClass GetDomFromShellDocObjectView(int hWnd) { object domObj = new object(); Guid riid = new Guid("626FC520-A41E-11CF-A731-00A0C9082637"); string lpString = "WM_HTML_GETOBJECT"; int wMsg = RegisterWindowMessageA(ref lpString); if (wMsg == 0) { throw new Exception("Unable to register windows message in getDOMFromHwnd()"); } int lResutl = SendMessageA(hWnd, wMsg, 0, 0); if (ObjectFromLresult( lResutl, ref riid, 0, out domObj) != 0) { throw new Win32Exception("Unable to get IE DOM from window message result in GetDomFromShellDocObjectView()"); } return domObj as HTMLDocumentClass; }
[DllImport("user32")] private static extern int RegisterWindowMessageA([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpString); [DllImport("user32")] private static extern int SendMessageA(int hWnd, int wMsg, int wParam, int lParam); [DllImport("oleacc")] private static extern int ObjectFromLresult(int lResult, ref Guid riid, int wParem, [MarshalAs(UnmanagedType.Interface)] out object pAcc); } } |
小结
1. 代码有很多注释,这里就不再赘述了,如有不明白,可以发邮件联系我。
附录
2. 联系方式:stainboyx@hotmail.com