Как подождать, пока WebBrowser не будет полностью загружен в VB.NET?

Я использую элемент управления WebBrowser в своем приложении VB.NET для загрузки нескольких URL-адресов (~ 10-15) и сохранения их источника HTML в текстовом файле. Однако мой код не записывает источник текущей страницы, а не исходный, потому что он запускается еще до загрузки страницы.

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

Я попробовал следующий код, но он не работает.

Do Until WebBrowser1.ReadyState = WebBrowserReadyState.Complete
   Application.DoEvents()
Loop

Ответы

Ответ 2

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

использование: просто вызовите WaitForPageLoad() сразу после вызова навигации

whatbrowser.Navigate("http://www.google.com")
WaitForPageLoad()

другой пример мы не комбинируем функцию навигации с загрузкой страницы, потому что иногда вам нужно ждать загрузки без навигации, например, вам может потребоваться дождаться загрузки страницы, которая была запущена с событием invokemember

whatbrowser.Document.GetElementById("UserName").InnerText = whatusername
whatbrowser.Document.GetElementById("Password").InnerText = whatpassword
whatbrowser.Document.GetElementById("LoginButton").InvokeMember("click")
WaitForPageLoad()

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

Теперь, где-нибудь в вашем модуле или классе, поместите это:

Private Property pageready As Boolean = False

#Region "Page Loading Functions"
    Private Sub WaitForPageLoad()
        AddHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
        While Not pageready
            Application.DoEvents()
        End While
        pageready = False
    End Sub

    Private Sub PageWaiter(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
        If whatbrowser.ReadyState = WebBrowserReadyState.Complete Then
            pageready = True
            RemoveHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
        End If
    End Sub

#End Region

Ответ 3

Технически, с кодом, опубликованным BGM, есть две проблемы:

  • Добавление обработчиков в метод WaitForPageLoad потенциально слишком поздно. Навигация начинается до добавления обработчиков, что означает, что в очень редких случаях, когда браузер уже имеет страницу, которую он может заполнить до добавления обработчиков, в этом случае вы будете пропускать событие и сидеть навечно.

    Решение состоит в том, чтобы добавить обработчики до начала навигации и удалить их после завершения навигации

    Это означает, что метод WaitForPageLoad нужно разделить на два метода. Один из них вызывается до начала навигации. Он должен установить обработчики. Вторая часть выполняет мониторинг ReadyState и очищает его, когда "Готов".

  • Хорошая практика программирования заключается в добавлении тайм-аута, так что потерянный (или разбитый или циклический) браузер не заставит ваш код ждать навсегда для документа, завершенного даже

Ответ 4

В течение некоторого времени я боролся с этой "полностью загруженной" проблемой, но нашел, что для меня работает следующее решение. Я использую IE7, поэтому я не уверен, что это работает в других версиях, но стоит посмотреть.

Я разделил проблему на две части; сначала мне понадобилось сообщение из события DocumentComplete;

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
   fullyLoaded = True
End Sub

Затем в той части кода, где мне нужно подождать, пока веб-страница полностью загрузится, я вызываю другой суб, который делает это:

Private Sub holdBrowserPage()
     fullyLoaded = False
     Do While fullyLoaded = False
         DoEvents
     Loop 
     fullyLoaded = False
End Sub

Кроме того, мне также нужно было сделать то же самое, ожидая завершения javascript-кода. Например, на одной странице, когда вы выбираете элемент из раскрывающегося списка html, он заполнил следующий выпадающий список, но потребовалось некоторое время, чтобы выявить себя. В этом случае я нашел это:

Private Sub holdBrowser()
Do While WebBrowser1.Busy Or WebBrowser1.ReadyState <> READYSTATE_COMPLETE
   DoEvents
Loop
End Sub

было достаточно, чтобы удержать браузер. Не уверен, что это поможет всем, как комбинация IE7, загружаемого мной веб-сайта, и javascript, который работает в одной странице, может позволить это решение, но, безусловно, стоит попробовать.

Ответ 5

В событиях загрузки используйте Me.Hide.

В WebBrowser1.DocuementCompleted используйте Me.Show

Ответ 6

Удерживайте...

Из моего опыта вам следует убедиться, что DocumCompleted принадлежит ВАШУ URL, а не к подстранице фрейма, script, изображению, CSS и т.д. И это независимо от IsBusy или ReadyState завершено или нет, что часто бывает неточным, если страница немного сложна.

Ну, это мой личный опыт, по рабочей программе VB.2013 и IE11. Позвольте мне также упомянуть, что вы должны учитывать также режим совместимости IE7, который по умолчанию включен в webBrowser1.

' Page, sub-frame or resource was totally loaded.
Private Sub webBrowser1_DocumentCompleted(sender As Object, _ 
    e As WebBrowserDocumentCompletedEventArgs) _ 
    Handles webBrowser1.DocumentCompleted

    ' Check if finally the full page was loaded (inc. sub-frames, javascripts, etc)
    If e.Url.ToString = webBrowser1.Url.ToString Then
        ' Only now you are sure!
        fullyLoaded = True
    End If

End Sub

Ответ 7

Несколько раз, если вы используете JavaScript, событие DocumentComplet не возвращает правильный ответ, я использую событие ProgressChanged

Private Sub WebBrowser1_ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs) _
 Handles WebBrowser1.ProgressChanged

    Console.WriteLine("CurrentProgress: " + e.CurrentProgress.ToString)
    If e.CurrentProgress = e.MaximumProgress Then
        'The maximun progres is reached
        load_stated = True
    End If
    'The page is confirmed downloaded after the pregres return to 0
    If e.CurrentProgress = 0 Then
        If load_stated Then
            'the page is ready to print or download...
            WebBrowser1.Print()
            load_stated = False
        End If
    End If
End Sub

Ответ 8

На самом деле это очень просто, попробуйте следующее:

While WebBrowser1.ReadyState <> WebBrowserReadyState.Complete
   Application.DoEvents()
End While

Ответ 9

Я сделал аналогичную функцию (только для меня это работает) - извините, что на С#, но легко перевести...

private void WaitForPageLoad ( ) {
 while (pageReady == false)
     Application.DoEvents();

  while (webBrowser1.IsBusy || webBrowser1.ReadyState !=   WebBrowserReadyState.Complete)
     Application.DoEvents();
}