使用AssemblyInstance.GetType(),Type.GetProperty()方法获得对目标属性的引用,然后使用PropertyInfo.GetValue()方法和方法委托(method delegate)来获得该属性。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Reflection; using System.Drawing; namespace TestingAUT { class Program { static void Main(string[] args) { try { Console.WriteLine("Launching Form...."); //Form theForm = null; string formName = "AUT.Form1"; string Path = @"C:/Users/btslabs/Desktop/TE/AUT/AUT/bin/Debug/AUT.exe"; Form theForm = LaunchApp(Path, formName); MoveForm(theForm, 10, 20); ReSizeForm(theForm, 300, 300); GetFormLocation(theForm); Console.WriteLine("AUT launched!"); Thread.Sleep(1500); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine("Fatal error: " + ex.Message); Console.ReadKey(); } } #region 模块1,运行待测程序. static Form LaunchApp(string path, string formName) { Form result = null; //首先获得一个待测程序窗体对象的引用 //通过工厂机制来创建Assembly对象。 Assembly a = Assembly.LoadFrom(path); //Type的使用,其实就是不知道类名以及类的成员信息的情况下,一种泛泛使用class的概念. Type t = a.GetType(formName); //createInstance()是Assembly对象的方法, 它的参数是被创建实例的全名. //全名称参数是通过一个Type对象来调用的. result = (Form)a.CreateInstance(t.FullName); //using the wrapper class and Thread to launch the App AppState aps = new AppState(result); //要创建一个ThreadStart对象,需要传一个目标方法(Target method)给ThreadStart的构造函数. //这个目标方法必须返回void类型 //当线程开始执行时,要调用的就是这个目标方法. ThreadStart ts = new ThreadStart(aps.RunApp); //要创建一个Thread对象,需要传一个ThreadStart对象给Thread的构造函数 Thread thread = new Thread(ts); thread.ApartmentState = ApartmentState.STA; thread.IsBackground = true; thread.Start(); return result; } #endregion #region 模块2,设置窗体属性,以达到移动窗体目的。 static void MoveForm(Form f, int x, int y) { Console.WriteLine("/nSetting Form1 Location to (x, y)"); System.Drawing.Point pt = new System.Drawing.Point(x, y); //创建一个对象数组,保存需要传给delegate的参数,然后这些参数会传给与delegate相关联的实际方法 object[] o = new object[] { f, "Location", pt }; SetFormProperty sfp1 = new SetFormProperty(); Delegate d = new SetFormPropertyValueHandler(sfp1.SetFormPropertyValue); if (f.InvokeRequired) { /*调用PropertyInfo.SetValue()方法时,并不是从窗体的主线程里,而是在由自动化测试程序所创建的一个线程里调用SetValue(), * 在这种情况下,不能直接调用SetValue(),而是以Form.Invoke()方法间接调用SetValue()。 从而确认测试代码与待测程序在一个进程中能通过线程相互通信。*/ f.Invoke(d, o); } else { Console.WriteLine("Unexpected logic flow"); } } #endregion #region 模块3,改变窗体大小 static void ReSizeForm(Form f, int Width, int Height) { Console.WriteLine("/nSetting Form1 Size to {0}*{1}",Width,Height); System.Drawing.Size size = new System.Drawing.Size(Width, Height); //创建一个对象数组,保存需要传给delegate的参数,然后这些参数会传给与delegate相关联的实际方法 object[] o = new object[] { f, "Size", size }; SetFormProperty sfp1 = new SetFormProperty(); Delegate d = new SetFormPropertyValueHandler(sfp1.SetFormPropertyValue); if (f.InvokeRequired) { /*调用PropertyInfo.SetValue()方法时,并不是从窗体的主线程里,而是在由自动化测试程序所创建的一个线程里调用SetValue(), * 在这种情况下,不能直接调用SetValue(),而是以Form.Invoke()方法间接调用SetValue()。 从而确认测试代码与待测程序在一个进程中能通过线程相互通信。*/ //对象数组o中的参数是供delegate委托d来使用的. f.Invoke(d, o); } else { Console.WriteLine("Unexpected logic flow"); } } #endregion #region 模块4, 获取窗体属性 static void GetFormLocation(Form f) { Console.WriteLine("/nGet the current form's location"); GetFormProperty gfp1 = new GetFormProperty(); Delegate d = new GetFormPropertyValueHandler(gfp1.GetFormPropertyValue); object[] o = new object[]{f,"Location"}; //不能从一个非主窗体线程里直接调用GetValue() if (f.InvokeRequired) { //因为我们是从测试程序所在的线程而不是受测的主窗体对象所在的线程来调用GetValue()的, //所以应该像下面这样通过调用Form.Invoke(),并使用委托delegate来达到这个目的。 Point p = (Point) f.Invoke(d, o); Console.WriteLine("Form1 Location = " + p.X + ", " + p.Y); } else { Console.WriteLine("Unexpected logic flow"); } } } #endregion //以下是一些外覆类和委托方法的定义 #region LaunchApp //定义一个外覆类以使Application.Run()传给ThreadStart class AppState { public Form myForm; public AppState(Form F) { this.myForm = F; } //目标是将一个有参数的方法转换成一个无参数的,且返回值为void的方法,供ThreadStart构造函数使用。 //因为ThreadStart构造函数使用一个委托,参数必须只是一个是无参数的方法名. public void RunApp() { Application.Run(myForm); } } #endregion #region SetProperty //定义一个用来设置属性的委托 delegate void SetFormPropertyValueHandler(Form f, string propertyName,object newValue); //创建一个“设置窗体属性类”,在其中定义一个实例方法供委托使用。 class SetFormProperty { //必须是实例方法,若是静态方法,在委托中使用不便 public void SetFormPropertyValue(Form f, string propertyName, object newValue) { //而PropertyInfo对象需要由一个Type对象调用 Type t = f.GetType(); //SetValue()方法又需要由一个PropertyInfo对象来调用, PropertyInfo pi = t.GetProperty(propertyName); //.NET中有一个PropertyInfo.SetValue()方法来设置窗体的属性 /*SetValue()方法的第一个参数是要操纵的对象,在本例中是指窗体Form对象。 第二个参数是要为该属性设置的新值,在本例中是一个新的Point对象。 第三个参数是因为有些属性是以索引的形式存在的, * 当属性不是以索引形式存在的时候,简单地传一个空值null作为它的参数 */ pi.SetValue(f, newValue, null); } } #endregion #region GetProperty //定义一个用来获取属性的委托 delegate object GetFormPropertyValueHandler(Form f, string propertyName); //创建一个"获取窗体属性类",在其中定义个实例方法供委托引用 class GetFormProperty { public object GetFormPropertyValue(Form f, string PropertyName) { //先获取一个类型对象t Type t = f.GetType(); //再获取一个属性对象Pi PropertyInfo pi = t.GetProperty(PropertyName); //调用属性对象的方法GetValue(),获取属性值 /*GetValue()方法的第一个参数是要操纵的对象,在本例中是指窗体Form对象。 * 第三个参数是因为有些属性是以索引的形式存在的, * 当属性不是以索引形式存在的时候,简单地传一个空值null作为它的参数*/ object result = pi.GetValue(f, null); return result; } } #endregion }