Подтвердить что ты не робот

С# как подождать, пока веб-страница завершит загрузку, прежде чем продолжить

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

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

Ответ 1

Попробуйте событие, завершенное документом

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

Ответ 2

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

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

Ответ 3

Лучший способ сделать это, не блокируя поток пользовательского интерфейса, - использовать 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);
        }
    }

И вы можете использовать его так: с помощью метода async или в событии нажатия кнопки просто сделайте его async:

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

Ответ 4

Просмотрите проект WatiN:

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

Ответ 5

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

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

Ответ 7

idk почему, но код yuna и bnl не удалось в приведенном ниже случае;

1-й из них ждет завершено. Но второй с invokemember ( "submit" ) не сделал. вызывать работы. но 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 html.");  
var html = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;

как устранить эту нежелательную ситуацию;

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

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

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


 //instead of checking  readState . we get state from DocumentCompleted Event via bool value
 bool webbrowserDocumentCompleted = false;
 public static void waitWebBrowserToComplete(WebBrowser wb)
 {
     while (!webbrowserDocumentCompleted )
     {
         Application.DoEvents();
     }
     webbrowserDocumentCompleted = false;
  }

  form_load(){
     wb.DocumentCompleted += (o, e) => {
        webbrowserDocumentCompleted = true;
      };
  }

Ответ 8

Если вы используете объект COM InternetExplorer.Application COM, проверьте свойство ReadyState на значение 4.

Ответ 9

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

Ответ 10

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

Ответ 11

while (true)
        {//ie is the WebBrowser object
            if (ie.ReadyState == tagREADYSTATE.READYSTATE_COMPLETE)
            {
                break;
            }
            Thread.Sleep(500);
        }

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

Ответ 12

Посмотрев на некоторые из вышеперечисленных ответов, я обнаружил общий недостаток. Вы не можете использовать любое из вышеперечисленных решений универсально. Это лучший способ:

private void let_Load(string url)
    {
        // Waits for page to load
        // If page doesn't load in 10 seconds, the while loop is exited with error
        Stopwatch s = new Stopwatch();
        s.Start();
        while (url != webbrowser1.Url.ToString())
        {
            Application.DoEvents();
            if (url == webbrowser1.Url.ToString())
                break;
            if (s.Elapsed > TimeSpan.FromSeconds(9.9))
                {
                richTextBox.Text = "Error: Page is unable to Load.";
                break;
                }
        }
    }

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

// Short Example
webbrowser1.Navigate("http://twitter.com");
let_load("http://twitter.com");

Быстрое примечание. Убедитесь, что веб-браузер уже имеет URL-адрес. Просто установите URL-адрес в свойствах, чтобы он загружался при запуске приложения.