2011-09-21 42 views
10

我正在試着用Watin 2.1.0測試文件與IE9的下載。我用從接受的答案建議代碼的問題Downloading a file with Watin in IE9,像這樣:如何使用Watin/IE9測試文件下載?

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

然而,downloadHandler.WaitUntilFileDownloadDialogIsHandled(15)調用超時。我該怎麼辦?

+0

嘗試等待更久?對於大文件,文件下載對話框可能需要一段時間才能顯示。 15秒看起來不夠長 –

+0

@Jeremy McGee該文件非常小,我已經驗證下載對話框確實出現。我甚至手動取消它,WaitUntilFileDownloadDialogIsHandled仍然超時。 – aknuds1

+0

嘗試使用DialogHandlerHelper來確定哪些WATIN認爲IE9下載對話窗口實際上是,因爲它在我看來IE9的下載對話不符合WATIN用來找到它的標準。 –

回答

8

IE9不再使用對話窗口來保存文件。相反,它使用通知欄來防止焦點從網站中刪除。請參閱「下載管理器」下的http://msdn.microsoft.com/en-us/ie/ff959805.aspx以供參考。

不幸的是,這意味着在華廷當前FileDownloadHandler將無法正常工作。它爲每個瀏覽器實例實例化一個「DialogWatcher」類,它是任何類型子窗口的基本消息泵。當遇到子窗口時,DialogWatcher會檢查該窗口是否是特定的對話框(通知欄不是)。如果它是一個對話框,它會遍歷調用「CanHandleDialog」的已註冊的IDialogHandler實例。即使通知欄是一個對話框,它也是一個不同的窗口樣式(http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx),這是WatiN如何檢測對話框的類型。

從我所看到的,有用於檢測IE 9通知欄及其在華廷提示不支持呢。在添加該支持之前,您將無法在IE9中自動下載文件。

+1

啊,你可能是對的,雖然我一直無法確認。 – aknuds1

+1

僅使用watin 2.1是不可能的,但使用以下關於UIAutomation *的方法,可以執行所有黃白條命令,包括open和save-as。 – tomsv

21

文件下載對話框不會在IE9(Windows7的)NetFramework 4.0。

下面的代碼片段可能會幫助您解決問題:

首先,你必須添加引用UIAutomationClient和UIAutomationTypes您的測試項目。

後在IE9工具 - >查看下載 - >選項定義你的保存文件夾路徑。 此外,如果你需要自動執行另存爲對話框:

如果你想點擊「另存爲」本

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; 

    } 
} 

編輯取代的foreach代碼的下一方法擴展瀏覽器類

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

指定一個路徑並單擊保存,您可以通過在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(); 
} 
+0

這真的很酷,但可以保存爲對話框自動保存爲特定的文件名?我已經嘗試修改代碼,但是當我試圖找到另存爲對話框時,我遇到了麻煩。 – PeteT

+1

解決了自動保存路徑並單擊保存,因此將代碼添加到答案中。希望沒關係。 – PeteT

+2

您可以使用「另存爲」發佈完整解決方案的github要點嗎?我很難在IE10中使用它。 – djbyter