如何使用Watin / IE9测试文件下载?

我正在尝试使用Watin 2.1.0对IE9测试文件下载。 我使用了在IE9中使用Watin下载文件的问题的接受答案中的建议代码,如下所示:

var downloadHandler = new FileDownloadHandler(fname); WebBrowser.Current.AddDialogHandler(downloadHandler); link.ClickNoWait(); downloadHandler.WaitUntilFileDownloadDialogIsHandled(15); downloadHandler.WaitUntilDownloadCompleted(200); 

但是, downloadHandler.WaitUntilFileDownloadDialogIsHandled(15)调用超时。 我该怎么办?

IE9不再使用对话窗口来保存文件。 相反,它使用通知栏来防止焦点从网站上删除。 请参阅“下载管理器”下的http://msdn.microsoft.com/en-us/ie/ff959805.aspx以供参考。

不幸的是,这意味着WatiN中的当前FileDownloadHandler将无法工作。 它为每个浏览器实例实例化一个“DialogWatcher”类,它是任何类型子窗口的基本消息泵。 遇到子窗口时,DialogWatcher会检查窗口是否是一个特定的对话框(通知栏不是)。 如果是对话框,则它会遍历已注册的IDialogHandler实例,并调用“CanHandleDialog”。 即使通知栏是一个对话框,它也是一个不同的窗口样式( http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx ),是WatiN如何检测对话类型。

从我所看到的,还没有支持检测IE 9通知栏及其在WatiN中的提示。 在添加该支持之前,您将无法在IE9中自动下载文件。

文件下载对话框在IE9(Windows7)NetFramework 4.0中不起作用。

以下代码段可能有助于您解决此问题:

首先,您必须将参考UIAutomationClient和UIAutomationTypes添加到测试项目中。

在Ie9工具后 – >查看下载 – >选项定义保存文件夹的路径。

下一个方法扩展了Browser类

 public static void DownloadIEFile(this Browser browser) { // see information here (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx) Window windowMain = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(browser.hWnd, 5)); System.Windows.Automation.TreeWalker trw = new System.Windows.Automation.TreeWalker(System.Windows.Automation.Condition.TrueCondition); System.Windows.Automation.AutomationElement mainWindow = trw.GetParent(System.Windows.Automation.AutomationElement.FromHandle(browser.hWnd)); Window windowDialog = new Window(WatiN.Core.Native.Windows.NativeMethods.GetWindow(windowMain.Hwnd, 5)); // if doesn't work try to increase sleep interval or write your own waitUntill method Thread.Sleep(1000); windowDialog.SetActivate(); System.Windows.Automation.AutomationElementCollection amc = System.Windows.Automation.AutomationElement.FromHandle(windowDialog.Hwnd).FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Condition.TrueCondition); foreach (System.Windows.Automation.AutomationElement element in amc) { // You can use "Save ", "Open", ''Cancel', or "Close" to find necessary button Or write your own enum if (element.Current.Name.Equals("Save")) { // if doesn't work try to increase sleep interval or write your own waitUntil method // WaitUntilButtonExsist(element,100); Thread.Sleep(1000); System.Windows.Automation.AutomationPattern[] pats = element.GetSupportedPatterns(); // replace this foreach if you need 'Save as' with code bellow foreach (System.Windows.Automation.AutomationPattern pat in pats) { // '10000' button click event id if (pat.Id == 10000) { System.Windows.Automation.InvokePattern click = (System.Windows.Automation.InvokePattern)element.GetCurrentPattern(pat); click.Invoke(); } } } } } 

如果您想点击“另存为”,请用此替换foreach代码

 System.Windows.Automation.AutomationElementCollection bmc = element.FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Automation.ControlViewCondition); System.Windows.Automation.InvokePattern click1 = (System.Windows.Automation.InvokePattern)bmc[0].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000)); click1.Invoke(); Thread.Sleep(10000); System.Windows.Automation.AutomationElementCollection main = mainWindow.FindAll(System.Windows.Automation.TreeScope.Children ,System.Windows.Automation.Condition.TrueCondition); foreach (System.Windows.Automation.AutomationElement el in main) { if (el.Current.LocalizedControlType == "menu") { // first array element 'Save', second array element 'Save as', third second array element 'Save and open' System.Windows.Automation.InvokePattern clickMenu = (System.Windows.Automation.InvokePattern) el.FindAll(System.Windows.Automation.TreeScope.Children, System.Windows.Automation.Condition.TrueCondition) [1].GetCurrentPattern(System.Windows.Automation.AutomationPattern.LookupById(10000)); clickMenu.Invoke(); //add ControlSaveDialog(mainWindow, filename) here if needed break; } } 

编辑:此外,如果您需要自动执行指定路径的保存对话框并单击保存,您可以通过在中断之前添加此代码来执行此操作;

 private static void ControlSaveDialog(System.Windows.Automation.AutomationElement mainWindow, string path) { //obtain the save as dialog var saveAsDialog = mainWindow .FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Save As")); //get the file name box var saveAsText = saveAsDialog .FindFirst(TreeScope.Descendants, new AndCondition( new PropertyCondition(AutomationElement.NameProperty, "File name:"), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit))) .GetCurrentPattern(ValuePattern.Pattern) as ValuePattern; //fill the filename box saveAsText.SetValue(path); Thread.Sleep(1000); //find the save button var saveButton = saveAsDialog.FindFirst(TreeScope.Descendants, new AndCondition( new PropertyCondition(AutomationElement.NameProperty, "Save"), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button))); //invoke the button var pattern = saveButton.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern; pattern.Invoke(); }