单击文件下载的Save或SaveAs对话框

时间:2015-06-04 08:08:58

标签: c# watin

我已经看到关于这个主题的几个问题,但没有一个解决方案能够解释我为什么再次发布它。

我正在使用WatIn自动测试我的网站。使用IE 11.我必须下载并保存文件,但我无法单击下载窗口的save或saveas按钮。我尝试过WatIn的FileDownloadHandler,但它没有用。 我不仅限于WatIn只有解决方案。它可能是我可以在我的C#代码中使用的任何东西都可以接受

FileDownloadHandler fileDownloadHandler = new FileDownloadHandler();
browser.AddDialogHandler(fileDownloadHandler);
browser.Image(Find.ByAlt("Download.Csv")).Ancestor("a").ClickNoWait();
fileDownloadHandler.WaitUntilFileDownloadDialogIsHandled(40);
fileDownloadHandler.WaitUntilDownloadCompleted(200);

2 个答案:

答案 0 :(得分:3)

WatiN没有与Windows控件完全交互,Windows中的帮助很少。我在处理Windows控件时遇到了同样的问题,因为我们有多个版本的IE。与< = IE 8.0版本相比,IE 9.0及更高版本具有不同的文件处理能力。以下适用于IE 9.0及更高版本。 请确保添加适当的引用(请参阅使用')。

using System.Threading;
using System.Windows.Automation;
using WatiN.Core;
using WatiN.Core.Native.Windows;

namespace TestFramework.Util
{
  public static class WindowsHelper
  {
    #region Public Methods

    /// <summary>
    /// Download IE file.
    /// </summary>        
    /// <param name="action">Action can be Save/Save As/Open/Cancel.</param>
    /// <param name="path">Path where file needs to be saved (for Save As function).</param>
    public static void DownloadIEFile(string action, string path = "", string regexPatternToMatch = "")
    {
        Browser browser = null;
        if (Utility.Browser != null) // Utility.Browser is my WatiN browser instance.
        {
            if (string.IsNullOrEmpty(regexPatternToMatch))
            {
                browser = Utility.Browser;
            }
            else
            {
                Utility.Wait(() => (browser = Browser.AttachTo<IE>(Find.ByUrl(new System.Text.RegularExpressions.Regex(regexPatternToMatch)))) != null);
            }
        }
        else
        {                
            return;
        }

        // If doesn't work try to increase sleep interval or write your own waitUntill method
        Thread.Sleep(3000);
        // See information here (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx)
        Window windowMain = null;
        Utility.Wait(() => (windowMain = new Window(NativeMethods.GetWindow(browser.hWnd, 5))).ProcessID != 0);

        TreeWalker trw = new TreeWalker(Condition.TrueCondition);
        AutomationElement mainWindow = trw.GetParent(AutomationElement.FromHandle(browser.hWnd));

        Window windowDialog = null;
        Utility.Wait(() => (windowDialog = new Window(NativeMethods.GetWindow(windowMain.Hwnd, 5))).ProcessID != 0);

        windowDialog.SetActivate();
        AutomationElementCollection amc = null;
        Utility.Wait(() => (amc = AutomationElement.FromHandle(windowDialog.Hwnd).FindAll(TreeScope.Children, Condition.TrueCondition)).Count > 1);

        foreach (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(action))
            {
                // If doesn't work try to increase sleep interval or write your own waitUntil method
                // WaitUntilButtonExsist(element,100);
                Thread.Sleep(1000);
                AutomationPattern[] pats = element.GetSupportedPatterns();

                // Replace this for each if you need 'Save as' with code bellow
                foreach (AutomationPattern pat in pats)
                {
                    // '10000' button click event id 
                    if (pat.Id == 10000)
                    {
                        InvokePattern click = (InvokePattern)element.GetCurrentPattern(pat);
                        click.Invoke();
                    }
                }
            }
            else if (element.Current.Name.Equals("Save") && action == "Save As")
            {
                AutomationElementCollection bmc = element.FindAll(TreeScope.Children, Automation.ControlViewCondition);
                InvokePattern click1 = (InvokePattern)bmc[0].GetCurrentPattern(AutomationPattern.LookupById(10000));
                click1.Invoke();
                Thread.Sleep(1000);

                AutomationElementCollection main = mainWindow.FindAll(TreeScope.Children, Condition.TrueCondition);
                foreach (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'
                        InvokePattern clickMenu = (InvokePattern)
                                    el.FindAll(TreeScope.Children, Condition.TrueCondition)[1].GetCurrentPattern(AutomationPattern.LookupById(10000));
                        clickMenu.Invoke();
                        Thread.Sleep(1000);

                        ControlSaveDialog(mainWindow, path);

                        break;
                    }
                }
            }
        }
    }


    /// <summary>
    /// Control for save dialog.
    /// </summary>
    /// <param name="mainWindow">Main window.</param>
    /// <param name="path">Path.</param>
    private static void ControlSaveDialog(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(500);
        Utility.PressKey("LEFT");
        Utility.PressKey("LEFT");
        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();
    }

    #endregion
}
}


public static class Utility
{       
    public static IE Browser { get; set; }

    // Wait specified number of seconds
    public static void Wait(int seconds)
    {
        System.Threading.Thread.Sleep(seconds * 1000);
    }

    // Wait for condition to evaluate true, timeout after 30 seconds
    public static void Wait(Func<bool> condition)
    {
        int count = 0;

        while (!condition() && count < 30)
        {
            System.Threading.Thread.Sleep(1000);
            count++;
        }
    }

    //Send tab key press to browser
    public static void PressTab()
    {
        System.Windows.Forms.SendKeys.SendWait("{TAB}");
        System.Threading.Thread.Sleep(300);
    }

    //Send specified key press to browser
    public static void PressKey(string keyname)
    {
        System.Windows.Forms.SendKeys.SendWait("{" + keyname.ToUpper() + "}");
        System.Threading.Thread.Sleep(300);
    }

}

希望这有帮助。

答案 1 :(得分:0)

我正在使用IE 11,并能够下载并关闭对话框

Automate of file download in IE 11 using c#