35

我正在尝试创建一个程序,通过我们的缺陷跟踪系统的 Web 界面一次克隆多个错误。在继续之前如何等待页面完全加载?

//This is pseudo code, but this should give you an idea of what I'm trying to do.  The
//actual code uses multi-threading and all that good stuff :).
foreach (string bug in bugs)
{
    webBrowser.Navigate(new Uri(url));
    webBrowser.Document.GetElementById("product").SetAttribute("value", product);
    webBrowser.Document.GetElementById("version").SetAttribute("value", version);
    webBrowser.Document.GetElementById("commit").InvokeMember("click");

    //Need code to wait for page to load before continuing.
}
4

11 回答 11

33

尝试DocumentCompleted事件:

webBrowser.DocumentCompleted +=
    new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);

void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    webBrowser.Document.GetElementById("product").SetAttribute("value", product);
    webBrowser.Document.GetElementById("version").SetAttribute("value", version);
    webBrowser.Document.GetElementById("commit").InvokeMember("click");
}
于 2009-02-24T22:30:23.007 回答
32

这段代码对我很有帮助。也许它也适合你

wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
     Application.DoEvents();
}
MessageBox.Show("Loaded");
于 2009-06-05T14:04:00.763 回答
20

在不阻塞 UI 线程的情况下执行此操作的最佳方法是使用 .net 4.5 中引入的 Async 和 Await。
您可以将其粘贴到您的代码中,只需将浏览器更改为您的网络浏览器名称。这样,您的线程等待页面加载,如果它没有按时加载,它将停止等待并且您的代码继续运行:

private async Task PageLoad(int TimeOut)
    {
        TaskCompletionSource<bool> PageLoaded = null;
        PageLoaded = new TaskCompletionSource<bool>();
        int TimeElapsed = 0;
        Browser.DocumentCompleted += (s, e) =>
        {
            if (Browser.ReadyState != WebBrowserReadyState.Complete) return;
            if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult(true);
        };
        //
        while (PageLoaded.Task.Status != TaskStatus.RanToCompletion)
        {
            await Task.Delay(10);//interval of 10 ms worked good for me
            TimeElapsed++;
            if (TimeElapsed >= TimeOut * 100) PageLoaded.TrySetResult(true);
        }
    }

您可以像这样使用它,在异步方法或按钮单击事件中,只需使其异步:

private async void Button1_Click(object sender, EventArgs e)
{
   Browser.Navigate("www.example.com");
   await PageLoad(10);//await for page to load, timeout 10 seconds.
   //your code will run after the page loaded or timeout.
}
于 2014-02-23T06:39:10.620 回答
12

查看WatiN 项目

Watir的启发,WatiN 的开发始于 2005 年 12 月,旨在为 .Net 语言提供类似的 Web 应用程序测试。从那时起,WatiN 已经成长为一个易于使用、功能丰富且稳定的框架。WatiN 是用 C# 开发的,旨在为您提供一种使用 .Net 使用 Internet Explorer 和 FireFox 自动化测试的简单方法...

于 2009-02-24T22:29:30.887 回答
8

任务方法对我有用,除了 Browser.Task.IsCompleted 必须更改为 PageLoaded.Task.IsCompleted。

对不起,我没有添加评论,那是因为我需要更高的声誉才能添加评论。

于 2014-05-02T15:34:51.143 回答
4

yuna 和 bnl 代码在以下情况下失败;

失败的例子:

第一个等待完成。但是,第二个带有 invokemember("submit") didt 。调用作品。但是 ReadyState.Complete 在它真正完成之前就像它的 Completed 一样:

wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
   Application.DoEvents();
}
MessageBox.Show("ok this waits Complete");

//navigates to new page
wb.Document.GetElementById("formId").InvokeMember("submit");
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
   Application.DoEvents();
}
MessageBox.Show("webBrowser havent navigated  yet. it gave me previous page's html.");  
var html = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;

如何解决这种不需要的情况:

用法

    public myForm1 {

        myForm1_load() { }

        // func to make browser wait is inside the Extended class More tidy.
        WebBrowserEX wbEX = new WebBrowserEX();

        button1_click(){
            wbEX.Navigate("site1.com");
            wbEX.waitWebBrowserToComplete(wb);

            wbEX.Document.GetElementById("input1").SetAttribute("Value", "hello");
            //submit does navigation
            wbEX.Document.GetElementById("formid").InvokeMember("submit");
            wbEX.waitWebBrowserToComplete(wb);
            // this actually waits for document Compelete. worked for me.

            var processedHtml = wbEX.Document.GetElementsByTagName("HTML")[0].OuterHtml;
            var rawHtml = wbEX.DocumentText;
         }
     }

//put this  extended class in your code.
//(ie right below form class, or seperate cs file doesnt matter)
public class WebBrowserEX : WebBrowser
{
   //ctor
   WebBrowserEX()
   {
     //wired aumatically here. we dont need to worry our sweet brain.
     this.DocumentCompleted += (o, e) => { webbrowserDocumentCompleted = true;};
   }
     //instead of checking  readState, get state from DocumentCompleted Event 
     // via bool value
     bool webbrowserDocumentCompleted = false;
     public void waitWebBrowserToComplete()
     {
       while (!webbrowserDocumentCompleted )
       { Application.DoEvents();  }
       webbrowserDocumentCompleted = false;
     }

 }
于 2017-01-05T12:43:01.283 回答
2

试试 Selenium ( http://seleniumhq.org ) 或 WatiN ( http://watin.sourceforge.net ) 以节省一些工作。

于 2009-02-24T22:45:54.967 回答
1

如果您使用 InternetExplorer.Application COM 对象,请检查 ReadyState 属性的值 4。

于 2009-02-24T22:28:56.287 回答
1

我认为 WebBrowser 控件的DocumentCompleted事件应该让您到达您需要去的地方。

于 2009-02-24T22:29:45.240 回答
1

假设“commit”元素代表一个标准的表单提交按钮,那么您可以将事件处理程序附加到 WebBrowsers Navigated 事件。

于 2009-02-24T22:31:47.763 回答
1
while (true)
        {//ie is the WebBrowser object
            if (ie.ReadyState == tagREADYSTATE.READYSTATE_COMPLETE)
            {
                break;
            }
            Thread.Sleep(500);
        }

我用这种方式等到页面加载。

于 2017-01-24T08:36:58.473 回答