C # как ждать загрузки веб-страницы, прежде чем продолжить - PullRequest
25 голосов
/ 25 февраля 2009

Я пытаюсь создать программу для клонирования нескольких ошибок одновременно через веб-интерфейс нашей системы отслеживания дефектов. Как я могу ждать, пока страница полностью загрузится, прежде чем продолжить?

//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.
}

Ответы [ 11 ]

31 голосов
/ 05 июня 2009

Этот код был очень полезным для меня. Может быть, это может быть и для вас

wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
     Application.DoEvents();
}
MessageBox.Show("Loaded");
25 голосов
/ 25 февраля 2009

Попробуйте событие 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");
}
18 голосов
/ 23 февраля 2014

Лучший способ сделать это без блокировки потока пользовательского интерфейса - использовать Async и Await, представленные в .net 4.5.
Вы можете вставить это в свой код, просто измените Браузер на имя вашего веб-браузера. Таким образом, ваш поток ожидает загрузки страницы, если он не загружается вовремя, он перестает ждать и ваш код продолжает работать:

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.
}
12 голосов
/ 25 февраля 2009

Ознакомьтесь с проектом WatiN :

Вдохновленный Watir Разработка WatiN началась в декабре 2005 года, чтобы сделать подобное тестирование веб-приложений возможным для языков .Net. С тех пор WatiN превратился в простой в использовании, многофункциональный и стабильный фреймворк. WatiN разработан на C # и призван предоставить вам простой способ автоматизации ваших тестов с помощью Internet Explorer и FireFox с использованием .Net ...

8 голосов
/ 02 мая 2014

Метод задачи работал для меня, за исключением того, что Browser.Task.IsCompleted должен быть изменен на PageLoaded.Task.IsCompleted

Извините, я не добавил комментарий, потому что мне нужна более высокая репутация, чтобы добавлять комментарии.

4 голосов
/ 05 января 2017

код yuna и bnl потерпел неудачу в случае ниже;

пример сбоя:

1-й ожидает завершения. Но 2-й с invokemember («представить») не сделал. вызвать работы. но ReadyState.Complete действует как Завершено до того, как ДЕЙСТВИТЕЛЬНО завершено:

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

 }
2 голосов
/ 25 февраля 2009

Пойдите в Selenium (http://seleniumhq.org) или WatiN (http://watin.sourceforge.net)), чтобы сэкономить на работе.

1 голос
/ 24 января 2017
while (true)
        {//ie is the WebBrowser object
            if (ie.ReadyState == tagREADYSTATE.READYSTATE_COMPLETE)
            {
                break;
            }
            Thread.Sleep(500);
        }

Я использовал этот способ ожидания до загрузки страницы.

1 голос
/ 25 февраля 2009

Предполагая, что элемент commit представляет стандартную кнопку отправки формы, вы можете присоединить обработчик события к событию WebBrowsers Navigated.

1 голос
/ 25 февраля 2009

Я думаю, что событие DocumentCompleted элемента управления WebBrowser должно привести вас туда, куда вам нужно.

...