¿Cómo probar la descarga de archivos con Watin / IE9?

Estoy intentando probar la descarga de archivos con Watin 2.1.0 contra IE9. Utilicé el código sugerido de la respuesta aceptada a la pregunta Descargando un archivo con Watin en IE9 , así:

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

Sin embargo, la llamada a downloadHandler.WaitUntilFileDownloadDialogIsHandled(15) expira. ¿Que debería hacer?

IE9 ya no usa una ventana de diálogo para guardar archivos. En cambio, usa la barra de notificaciones para evitar que el foco se elimine del sitio web. Consulte http://msdn.microsoft.com/en-us/ie/ff959805.aspx en “Administrador de descargas” para referencia.

Desafortunadamente, esto significa que el actual FileDownloadHandler en WatiN no funcionará. Instala una clase “DialogWatcher” por instancia de navegador que es una bomba de mensajes básica para cualquier tipo de ventana secundaria. Cuando se encuentran ventanas secundarias, DialogWatcher comprueba si la ventana es específicamente un diálogo (que no es la barra de notificaciones). Si se trata de un diálogo, entonces itera sobre las instancias de IDialogHandler registradas que llaman “CanHandleDialog”. Incluso si la barra de notificaciones fuera un cuadro de diálogo, es de un Estilo de ventana diferente ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx ), que es cómo WatiN detecta el tipo de diálogo.

Por lo que puedo ver, todavía no hay soporte para detectar la barra de notificaciones de IE 9 y sus indicaciones en WatiN. Hasta que se agregue esa compatibilidad, no podrá automatizar la descarga de archivos en IE9.

El diálogo de descarga de archivos no funciona en IE9 (Windows7) NetFramework 4.0.

El siguiente fragmento de código puede ayudarlo a resolver el problema:

Primero debe agregar las referencias UIAutomationClient y UIAutomationTypes a su proyecto de prueba.

Después, en Ie9 Herramientas -> Ver Descargas -> Opciones, defina la ruta a su carpeta de guardado.

El siguiente método amplía la clase de navegador

 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(); } } } } } 

si desea hacer clic en ‘Guardar como’, reemplace el código foreach con este

 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; } } 

Editar: También si necesita automatizar el guardado como diálogo que especifica una ruta y hacer clic en guardar, puede hacerlo agregando este código justo antes de la interrupción;

 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(); }