7.1 启动IE并连接到这个实例
问题
如何启动IE浏览器的一个实例并设法连接到这个实例,以便能够通过程序来操纵、同步,以及检查待测Web程序。
设计
通过Process.Start()方法启动IE的一个实例并取得返回的进程对象。然后实例化一个InternetExplorer对象并把这个InternetExplorer对象的句柄与前面得到的进程句柄相关联。
方案
try
{
InternetExplorer ie = null;
Console.WriteLine("\nLaunching an instance of IE");
Process p = Process.Start("iexplore.exe", "about:blank");
if (p == null)
throw new Exception("Could not launch IE");
Console.WriteLine("Process handle = " + p.MainWindowHandle.ToString());
SHDocVw.ShellWindows allBrowsers = new SHDocVw.ShellWindows();
Console.WriteLine("Number active browsers = " + allBrowsers.Count);
if (allBrowsers.Count == 0)
throw new Exception("Cannot find IE");
Console.WriteLine("Attaching to IE");
int i = 0; // 连接到合适的浏览器
while (i < allBrowsers.Count && ie == null)
{
InternetExplorer e = (InternetExplorer)allBrowsers.Item(i);
if (e.HWND == (int)p.MainWindowHandle)
ie = e;
++i;
}
if (ie == null)
throw new Exception("Failed to attach to IE");
}
catch(Exception ex)
{
Console.WriteLine("Fatal error: " + ex.Message);
}
我们可以通过System.Diagnostics命名空间里的Process.Start()静态方法启动IE程序。但是,现在就有了两个不同的进程,而测试套件不能直接与Web浏览器进行通信。为了解决这个问题,我们可以从shdocvw.dll中实例化一个InternetExplorer对象,然后把IE程序/进程的进程句柄赋给这个InternetExplorer对象。这样就能从测试套件里直接访问IE程序了。
注解
我们应该首先使用“iexplore.exe”和“about:blank”作为参数调用Process.Start()。请注意,必须把Start()的返回值取回,并赋给一个Process对象。如果不加载空页面“about:blank”,也可以在此时加载待测的Web页面。但是,经验显示,等连接到IE程序之后加载待测页面,这样自动化测试出问题的可能性就会小一些。此外,如果这时候启动IE失败,我们可以知道这个错误与待测程序无关。
启动IE程序之后,我们通过ShellWindows()方法实例化并取回所有活动的浏览器对象的一个集合。ShellWindows()方法位于shdocvw.dll这个API库中。要访问ShellWindows(),必须为自动化测试套件添加一个工程引用,这个工程引用指向Microsoft Internet Controls组件,这个组件位于传统的COM引用列表里。(请注意,与使用.NET的工程引用不同,如何判定某个DLL里的COM组件名称或函数名称,有时候并不是显而易见的。).NET框架把schdocvw.dll列集到(marshal)一个叫作SHDocVw的.NET命名空间;如果不想以全名称的形式引用InternetExplorer类或者来自shdocvw.dll库的其他类或对象,则可以在测试套件里加上下面这句代码:
using SHDocVw;
由ShellWindows()所返回的浏览器对象的集合,包含刚刚启动的那个IE实例,以及以前启动的IE程序,还有正在运行的Windows Explorer实例。我们必须遍历这个集合以找到哪一个是用于测试的IE实例。要做到这一点,首先应该实例化一个InternetExplorer对象,这个对象也是在SHDocVw命名空间里定义的。我们所采取的方案是,通过一个初始值为0的索引变量和while循环遍历这个集合:
while (i < allBrowsers.Count && ie == null)
当遍历完集合中所有的shell window对象却没有找到用于测试的IE程序或者InternetExplorer对象不等于null时,退出循环。对于第一种情况,意味着测试套件存在致命的逻辑上的缺陷,应该抛出一个异常。对于第二种情况,则意味着成功找到用于测试的IE程序。当测试程序发现当前shell window对象的HWND(窗口句柄)与用于测试的IE进程的MainWindowHandle属性相匹配时,就会把当前的InternetExplorer对象连接到正在运行的IE程序:
if (e.HWND == (int)p.MainWindowHandle)
ie = e;
请注意,因为shdocvw.dll是在.NET发布之前就已经存在的非受控程序(pre-.NET unmanaged library),所以InternetExplorer对象的HWND(句柄)成员实际上就是一个整型变量。但是.NET进程对象的MainWindowHandle的类型则是IntPtr,IntPtr是一个平台相关的.NET类型,它可以表示指针(内存地址),也可以表示句柄。要让这两个值能够通过“= =”运算符进行比较,我们需要把IntPtr类型转换成int。
对于某些测试情况,我们可能想要设置一个前提条件以确保没有其他的IE实例或者其他浏览器在运行。这可以消除潜在的浏览器之间交互的负面影响。如果碰到这种情况,在启动IE进程之后,可以检查ShellWindows集合,以确保除了用于测试的IE实例,没有其他的浏览器处于活动状态,然后就可以把InternetExplorer对象连接到ShellWindows集合中唯一的元素。
InternetExplorer ie = null;
if (allBrowsers.Count > 1)
throw new Exception("Other browser instances found");
else
ie = (InternetExplorer)allBrowsers.Item(0);







