¿Cómo esperar hasta que WebBrowser esté completamente cargado en VB.NET?

Estoy usando el control WebBrowser en mi aplicación VB.NET para cargar algunas URL (~ 10-15) y guardar su fuente HTML en un archivo de texto. Sin embargo, mi código no escribe el origen de la página actual en lugar de la fuente inicial porque se desencadena incluso antes de que se cargue la página.

¿Cómo puedo esperar hasta que la página esté completamente cargada antes de llamar a un evento?

Probé el siguiente código pero no funciona.

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

Parece que quieres ver el evento DocumentCompleted de tu control de navegador web.

MSDN tiene un par de buenos artículos sobre el control del navegador web: la clase WebBrowser tiene muchos ejemplos y Cómo agregar capacidades del navegador web a una aplicación de Windows Forms.

Salvete! Necesitaba, simplemente, una función a la que podía llamar para que el código esperara a que la página se cargara antes de continuar. Después de buscar en la red de respuestas, y jugando durante varias horas, se me ocurrió esto para resolver por mí mismo, el dilema exacto que presenta. Sé que llego tarde al juego con una respuesta, pero deseo publicar esto para cualquier otra persona que aparezca.

uso: simplemente llame a WaitForPageLoad () justo después de una llamada a la navegación

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

otro ejemplo no combinamos la función de navegación con la carga de la página, porque a veces necesita esperar una carga sin navegar, por ejemplo, puede que tenga que esperar a que se cargue una página que se inició con un evento invokemember

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

Aquí está el código: necesita ambos subs más la variable accesible, pageready . En primer lugar, asegúrese de corregir la variable llamada whatbrowser para que sea su control de whatbrowser

Ahora, en algún lugar de su módulo o clase, coloque esto:

 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 

Técnicamente, hay dos problemas con el código publicado por BGM:

  1. la adición de los controladores en el método WaitForPageLoad es potencialmente demasiado tarde. La navegación se inicia antes de que se agreguen los controladores, lo que significa que en casos muy raros donde el navegador ya tiene la página puede completarse antes de que se agreguen los controladores, en cuyo caso se perderá el evento y se quedará esperando por siempre.

    La solución es agregar los controladores antes de que comience la navegación y eliminarlos después de que la navegación se complete

    Esto significa que el método WaitForPageLoad necesita dividirse en dos métodos. Se llama a uno antes de iniciar la navegación. Debería configurar los controladores. La segunda parte hace la supervisión ReadyState y se limpia cuando está ‘Listo’.

  2. buenas prácticas de progtwigción es agregar un tiempo de espera para que un navegador perdido (o bloqueado o en bucle) no haga que su código espere para siempre hasta que el documento se complete, incluso

Algunas veces, si utiliza JavaScript, el evento DocumentComplet no devuelve la respuesta correcta, utilizo el evento 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 

Luché con este tema “completamente cargado” durante algún tiempo, pero descubrí que la siguiente solución funcionó para mí. Estoy usando IE7, así que no estoy seguro de si esto funciona en otras versiones, pero vale la pena echarle un vistazo.

Dividí el problema en dos partes; primero necesitaba un mensaje del evento DocumentComplete;

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

Luego, en la parte del código donde tengo que esperar hasta que la página web se haya cargado por completo, llamo a otro sub que hace esto;

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

Además, también necesitaba hacer lo mismo mientras esperaba que se completara el código de JavaScript. Por ejemplo, en una página cuando seleccionas un elemento de una lista desplegable html, llenó la siguiente lista desplegable, pero tardó un poco en revelarse. En esa instancia encontré llamar esto;

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

fue suficiente para mantener el navegador. No estoy seguro de si esto ayudará a todos, ya que una combinación de IE7, el sitio web que estaba cargando y el javascript que la página estaba ejecutando solo podría haber permitido esta solución, pero ciertamente vale la pena intentarlo.

Espere…

Desde mi experiencia, DocumCompleted asegurarte de que el DocumCompleted pertenezca a TU URL y no a una subpágina de un marco, guión, imagen, CSS, etc. Y eso independientemente de si IsBusy o ReadyState están terminados o no, que ambos son a menudo inexacta cuando la página es un poco compleja.

Bueno, esa es mi propia experiencia personal, en un progtwig de trabajo de VB.2013 e IE11. Permítanme mencionar también que debe tener en cuenta también el modo de compatibilidad IE7 que está activado por defecto en el 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 

En los eventos de carga, use Me.Hide .

En WebBrowser1.DocumentCompleted, use Me.Show

Hice una función similar (solo eso me funciona), lo siento en C #, pero es fácil de traducir …

 private void WaitForPageLoad ( ) { while (pageReady == false) Application.DoEvents(); while (webBrowser1.IsBusy || webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents(); } 

En realidad, es realmente fácil. Prueba esto:

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