Come aspettare che WebBrowser sia completamente caricato in VB.NET?

Sto usando il controllo WebBrowser nella mia applicazione VB.NET per caricare alcuni URL (~ 10-15) e salvare la loro sorgente HTML in un file di testo. Tuttavia, il mio codice non scrive l’origine della pagina corrente piuttosto quella iniziale perché viene triggersta anche prima che la pagina venga caricata.

Come posso aspettare che la pagina sia completamente caricata prima di chiamare qualsiasi evento?

Ho provato il seguente codice ma non funziona.

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

Sembra che tu voglia intercettare l’evento DocumentCompleted del tuo controllo del browser.

MSDN contiene un paio di buoni articoli sul controllo webbrowser: la class WebBrowser contiene molti esempi e Procedura: aggiungere funzionalità browser Web a un’applicazione Windows Form

Salvete! Avevo bisogno, semplicemente, di una funzione che potrei chiamare per fare in modo che il codice attenda che la pagina si carichi prima di continuare. Dopo aver setacciato il web per trovare le risposte e aver continuato a giocherellare per diverse ore, mi sono inventato questo per risolvere da solo il dilemma esatto che hai presentato. So di essere in ritardo nel gioco con una risposta, ma desidero postare questo per chiunque altro arrivi.

utilizzo: basta chiamare WaitForPageLoad () subito dopo una chiamata alla navigazione

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

un altro esempio non combiniamo la funzionalità di navigazione con il caricamento della pagina, perché a volte è necessario attendere un caricamento senza navigare, ad esempio, potrebbe essere necessario attendere il caricamento di una pagina avviata con un evento di richiamo

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

Ecco il codice: hai bisogno di entrambi i pageready più la variabile accessibile, pageready . Innanzitutto, assicurati di correggere la variabile chiamata whatbrowser come controllo del tuo browser

Ora, da qualche parte nel tuo modulo o class, posiziona questo:

 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 

Tecnicamente, ci sono due problemi con il codice pubblicato da BGM:

  1. l’aggiunta di gestori nel metodo WaitForPageLoad è potenzialmente troppo tardi. La navigazione viene avviata prima dell’aggiunta dei gestori, il che significa che in casi molto rari in cui il browser ha già la pagina potrebbe essere completata prima che vengano aggiunti i gestori, nel qual caso perderai l’evento e rimarrai seduto per sempre in attesa.

    La soluzione è aggiungere i gestori prima che inizi la navigazione e rimuoverli dopo la navigazione completata

    Ciò significa che il metodo WaitForPageLoad deve essere diviso in due metodi. Uno è chiamato prima di iniziare la navigazione. Dovrebbe impostare i gestori. La seconda parte fa il monitoraggio ReadyState e pulisce quando ‘Pronto’.

  2. buone pratiche di programmazione consiste nell’aggiungere un timeout in modo che un browser smarrito (o bloccato o in loop) non faccia aspettare il codice per sempre, anche se il documento è completato

Alcune volte se usi JavaScript l’evento DocumentComplet non restituisce la risposta giusta, io uso l’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 

Ho faticato con questo problema “a pieno carico” per un po ‘di tempo ma ho trovato che la seguente soluzione ha funzionato per me. Sto usando IE7, quindi non sono sicuro che funzioni in altre versioni, ma vale la pena dare un’occhiata.

Ho diviso il problema in due parti; prima avevo bisogno di un messaggio dall’evento DocumentComplete;

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

Poi nella parte del codice in cui devo aspettare che la pagina web sia completamente caricata, chiamo un altro sub che fa questo;

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

Inoltre, avevo anche bisogno di fare la stessa cosa mentre aspettavo il completamento del codice javascript. Ad esempio, in una pagina quando si seleziona un elemento da un elenco a discesa HTML, è stato compilato il successivo elenco a discesa, ma ci è voluto un po ‘per rivelare se stesso. In quel caso ho trovato la chiamata a questo;

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

era abbastanza per contenere il browser. Non sono sicuro se questo aiuterà tutti, come una combinazione di IE7, il sito web che stavo caricando, e il javascript che la pagina era in esecuzione da sola avrebbe potuto consentire questa soluzione, ma sicuramente vale la pena provare.

Resisti…

Dalla mia esperienza, dovresti assicurarti che DocumCompleted appartenga al TUO URL e non a una sotto-pagina di cornice, a uno script, a un’immagine, a un CSS, ecc. E questo indipendentemente IsBusy o dal ReadyState finito, che sono entrambi spesso inaccurato quando la pagina è leggermente complessa.

Bene, questa è la mia esperienza personale, su un programma di lavoro di VB.2013 e IE11. Permettetemi di menzionare anche che dovreste prendere in considerazione anche la modalità di compatibilità IE7 che è ON di default sul 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 

Negli eventi di caricamento, utilizzare Me.Hide .

In WebBrowser1.DocuementCompleted, utilizzare Me.Show

Ho fatto una funzione simile (solo che funziona per me) – mi dispiace è in C # ma facile da tradurre …

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

In realtà è davvero facile, prova questo:

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