Скачивание файла с помощью Watin в IE9 - PullRequest
7 голосов
/ 25 мая 2011

У меня проблема с автоматизацией процесса загрузки файла с веб-сайта.На веб-сайте есть кнопка 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!
}

Ответы [ 5 ]

5 голосов
/ 31 мая 2011

Это должно поддерживаться начиная с версии 1.1.0.4000. Примечания к выпуску для этой версии больше не доступны (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);
}

EDIT: После комментариев ниже, этот ответ был принят. Поэтому я предполагаю, что работает следующий код (который взят из ссылки на 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);
}
2 голосов
/ 30 октября 2013

Принятый ответ не сработал для меня, потому что в IE 9 появляется «Уведомление», по которому нужно перейти, прежде чем вы сможете перейти к реальному диалоговому окну «Сохранить как» (а WatiN не может обрабатывать уведомления автоматически). Я пошел по ссылке Борриса Павлова, который хорошо показал дорогу. Я немного почистил код, который был размещен там, и это был полученный файл:

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

См. Комментарий в методе ControlSaveDialog для получения информации о том, как заставить эту работу работать как отладочная сборка (настройки VS).

Я на самом деле тестировал только операцию «Сохранить как», поэтому я надеюсь, что другие работы (кажется, что оригинальный постер добавил «Сохранить как» в качестве запоздалой мысли, поэтому я предполагаю, что он проверил операцию «Сохранить» более тщательно) .

Для вызова этого кода вы можете использовать такой код, как:

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
1 голос
/ 16 декабря 2011

Watin не может найти диалог загрузки и кнопки диалога. Это может решить с этим.

Как проверить загрузку файла с помощью Watin / IE9?

Смотрите комментарии

1 голос
/ 29 ноября 2011

Я только что получил сообщение из списка рассылки пользователей Watin, что FileDownloadHandler не работает с IE9.Исправления пока нет, однако я удалил IE9 (откат к IE8), и у него есть диалог старого стиля, который обрабатывается WatiN.

0 голосов
/ 19 мая 2016

После многих ревизий с использованием WaitN я в конечном итоге использовал Selenium.Это дает вам гораздо больше контроля над тем, что обрабатывается и используется, и позволяет вам использовать более современные веб-браузеры.

...