Как подождать, пока WebBrowser не будет полностью загружен в VB.NET?
Я использую элемент управления WebBrowser в своем приложении VB.NET для загрузки нескольких URL-адресов (~ 10-15) и сохранения их источника HTML в текстовом файле. Однако мой код не записывает источник текущей страницы, а не исходный, потому что он запускается еще до загрузки страницы.
Как я могу подождать, пока страница полностью загрузится, прежде чем вызывать какое-либо событие?
Я попробовал следующий код, но он не работает.
Do Until WebBrowser1.ReadyState = WebBrowserReadyState.Complete
Application.DoEvents()
Loop
Ответы
Ответ 1
Похоже, вы хотите поймать событие DocumentCompleted вашего элемента управления веб-браузером.
В MSDN есть несколько хороших статей об управлении веб-браузером - WebBrowser Class имеет множество примеров и Как добавить возможности веб-браузера в приложение Windows Forms
Ответ 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();
}