在IE9中使用Watin下载文件

我在自动化从网站下载文件的过程中遇到了问题。 该网站有一个Java按钮,单击该按钮会触发下载Excel文件。 我正在使用最新版本的Watin (v2.1)。

我设法让Watin登录网站,导航到相应的页面,更改页面上的参数,然后单击按钮开始下载。

但是,当下载完成后,IE9下载框出现,没有任何反应,直到Watin超时。

我很感激任何建议,因为我看不到任何下载文件或保存文件的方法。 即使它将“Alt + S”传递给页面,也可以保存它。 我试过通过WatinTestRecorder运行它,并没有提示保存。

using (var browser = new IE(sLogin)) { browser.AddDialogHandler(new OKDialogHandler()); browser.AddDialogHandler(new DialogHandlerHelper()); browser.AddDialogHandler(new ConfirmDialogHandler()); browser.AddDialogHandler(new ReturnDialogHandlerIe9()); browser.TextField(Find.ByName("txtUserID")).TypeText("username"); browser.TextField(Find.ByName("txtPassword")).TypeText("password"); browser.Button(Find.ByName("btnLogin")).Click(); browser.WaitForComplete(); browser.GoTo(targetUri); browser.SelectList("ctl00_phFormContent_ucOptionParam0_lst").SelectByValue("4"); browser.Button(Find.ByName("ctl00$phFormButtonBar$btnRun")).Click(); browser.WaitForComplete(); //Some code to download the file here! } 

从版本1.1.0.4000开始应该支持此function。 该版本的发行说明不再在线( http://watin.org/documentation/ ),但我在Googles缓存中找到它( http://svn6.assembla.com/svn/ci-samples/dotnet/ watir / website / releasenotes-1-1-0-4000.html )

它应该是这样的:

 using(IE ie = new IE(someUrlToGoTo)) { FileDownloadHandler fileDownloadHandler = new FileDownloadHandler(fullFileName); ie.AddDialogHandler(fileDownloadHandler); ie.Link("startDownloadLinkId").Click(); fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(15); fileDownloadHandler.WaitUntilDownloadCompleted(200); } 

编辑:在下面的评论之后,这个答案被接受了。 所以我假设以下代码有效(这是从我上次评论中链接到SourceForge,注意ClickNoWait):

 using(IE ie = new IE(someUrlToGoTo)) { FileDownloadHandler fileDownloadHandler = new FileDownloadHandler(fullFileName); ie.AddDialogHandler(fileDownloadHandler); ie.Link("startDownloadLinkId").ClickNoWait(); fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(15); fileDownloadHandler.WaitUntilDownloadCompleted(200); } 

接受的答案对我不起作用,因为IE 9会弹出“通知”,您必须先导航才能进入实际的“另存为”对话框(并且WatiN无法自动处理通知)。 我跟随了Borris Pavlov的链接,这显示了方法。 我清理了那里发布的代码,这是生成的文件:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using WatiN.Core; using WatiN.Core.Native.Windows; using System.Threading; using System.Windows.Automation; namespace MyProject { public static class BrowserExtensionMethods { public static void DownloadIeFile(this IE browser,string saveAsFilename=null) { // see information here (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx) Window windowMain = new Window(NativeMethods.GetWindow(browser.hWnd, 5)); TreeWalker dialogElementTreeWalker = new TreeWalker(Condition.TrueCondition); AutomationElement mainWindow = dialogElementTreeWalker.GetParent(AutomationElement.FromHandle(browser.hWnd)); Window windowDialog = new Window(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(); AutomationElementCollection dialogElements = AutomationElement.FromHandle(windowDialog.Hwnd).FindAll(TreeScope.Children, Condition.TrueCondition); if (string.IsNullOrEmpty(saveAsFilename)) { ClickSave(dialogElements); } else { ClickSaveAs(mainWindow, dialogElements,saveAsFilename); } } private static void ClickSaveAs(AutomationElement mainWindow, AutomationElementCollection dialogElements,string filename) { foreach (AutomationElement element in dialogElements) { if (element.Current.Name.Equals("Save")) { AutomationElementCollection dialogSubElements = element.FindAll(TreeScope.Children, Automation.ControlViewCondition); InvokePattern clickPatternForSaveDropdown = (InvokePattern)dialogSubElements[0].GetCurrentPattern(AutomationPattern.LookupById(10000)); clickPatternForSaveDropdown.Invoke(); Thread.Sleep(3000); AutomationElementCollection dialogElementsInMainWindow = mainWindow.FindAll(TreeScope.Children, Condition.TrueCondition); foreach (AutomationElement currentMainWindowDialogElement in dialogElementsInMainWindow) { if (currentMainWindowDialogElement.Current.LocalizedControlType == "menu") { // first array element 'Save', second array element 'Save as', third second array element 'Save and open' InvokePattern clickMenu = (InvokePattern)currentMainWindowDialogElement.FindAll(TreeScope.Children, Condition.TrueCondition)[1].GetCurrentPattern(AutomationPattern.LookupById(10000)); clickMenu.Invoke(); Thread.Sleep(5000); ControlSaveDialog(mainWindow, filename); break; } } } } } private static void ClickSave(AutomationElementCollection dialogElements) { foreach (AutomationElement element in dialogElements) { // 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); AutomationPattern[] automationPatterns = element.GetSupportedPatterns(); // replace this foreach if you need 'Save as' with code bellow foreach (AutomationPattern currentPattern in automationPatterns) { // '10000' button click event id if (currentPattern.Id == 10000) { InvokePattern click = (InvokePattern)element.GetCurrentPattern(currentPattern); click.Invoke(); } } } } } private static void ControlSaveDialog(AutomationElement mainWindow, string path) { //obtain the save as dialog //*** must disable throwing of the NonComVisibleBaseClass "exception" for this to work in debug mode: // 1. Navigate to Debug->Exceptions... // 2. Expand "Managed Debugging Assistants" // 3. Uncheck the NonComVisibleBaseClass Thrown option. // 4. Click [Ok] //***copied from http://social.msdn.microsoft.com/Forums/en-US/27c3bae8-41fe-4db4-8022-e27d333f714e/noncomvisiblebaseclass-was-detected?forum=Vsexpressvb var saveAsDialog = mainWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Save As")); //var saveAsDialog = mainWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "[#] Save As [#]")); //needed if using sandboxie //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(); } } } 

有关如何使其作为调试版本(VS设置)的信息,请参阅ControlSaveDialog方法中的注释。

我实际上只测试了“另存为”操作,所以我希望其他工作(似乎原始海报添加了“另存为”作为事后的想法,所以我的猜测是他更彻底地测试了“保存”操作)。

要调用它,您可以使用以下代码:

 Link lastMp4Link = mp4Links[mp4Links.Count - 1]; //mp4Links is a WatiN.Core.LinkCollection lastMp4Link.Click(); browser.DownloadIeFile(string.Format(@"c:\temp\myFile.blah")); //"browser" is a WatiN.Core.IE object 

我刚从Watin-users邮件列表中得到了FileDownloadHandler被IE9破坏的消息。 目前还没有修复,但是我卸载了IE9(回滚到IE8)并且它具有由WatiN处理的旧样式对话框。

Watin找不到下载对话框和对话框按钮。 它可以解决这个问题。

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

看评论

在使用WaitN进行多次修改后,我最终使用了Selenium。 它使您可以更好地控制正在处理和使用的内容,并允许您使用更现代的Web浏览器。