web-dev-qa-db-fra.com

Comment attendre que WebBrowser soit complètement chargé dans VB.NET?

J'utilise le contrôle WebBrowser dans mon application VB.NET pour charger quelques URL (~ 10-15) et enregistrer leur source HTML dans un fichier texte. Cependant, mon code n'écrit pas la source de la page en cours plutôt que la première car elle est déclenchée avant même le chargement de la page.

Comment puis-je attendre que la page soit complètement chargée avant d'appeler un événement?

J'ai essayé le code suivant mais cela ne fonctionne pas.

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

On dirait que vous voulez attraper l'événement DocumentCompleted de votre contrôle webbrowser.

MSDN a quelques bons articles sur le contrôle webbrowser - WebBrowser Class a beaucoup d'exemples, et Comment: ajouter des fonctionnalités de navigateur Web à une application Windows Forms

7
Dan F

Salvete! J'avais besoin, simplement, ne fonction que je pouvais appeler pour que le code attende que la page se charge avant de continuer. Après avoir parcouru le Web pour trouver des réponses, et tripoter pendant plusieurs heures, j'ai trouvé ceci pour résoudre moi-même le dilemme exact que vous présentez. Je sais que je suis en retard dans le jeu avec une réponse, mais je souhaite publier ceci pour toute autre personne qui viendra.

sage: appelez simplement WaitForPageLoad () juste après un appel à la navigation

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

n autre exemple nous ne combinons pas la fonction de navigation avec le chargement de la page, car parfois vous devez attendre un chargement sans naviguer également, par exemple, vous devrez peut-être attendre qu'une page se charge qui était a commencé avec un événement invokemember

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

Voici le code: Vous avez besoin des deux sous-marins plus la variable accessible, pageready. Tout d'abord, assurez-vous de corriger la variable appelée whatbrowser pour être votre contrôle webbrowser

Maintenant, quelque part dans votre module ou classe, placez ceci:

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
21
bgmCoder

Parfois, si vous utilisez JavaScript, l'événement DocumentComplet ne renvoie pas la bonne réponse, j'utilise l'événement 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
3
Tronzeus

Techniquement, il y a deux problèmes avec le code publié par BGM:

  1. l'ajout des gestionnaires dans la méthode WaitForPageLoad est potentiellement trop tard. La navigation est lancée avant l'ajout des gestionnaires, ce qui signifie que dans de très rares cas où le navigateur a déjà la page, elle peut se terminer avant l'ajout des gestionnaires, auquel cas vous allez manquer l'événement et vous asseoir pour toujours.

    La solution consiste à ajouter les gestionnaires avant le début de la navigation et à les supprimer une fois la navigation terminée

    Cela signifie que la méthode WaitForPageLoad doit être divisée en deux méthodes. L'un est appelé avant de lancer la navigation. Il devrait définir les gestionnaires. La deuxième partie effectue la surveillance ReadyState et nettoie lorsqu'elle est "prête".

  2. les bonnes pratiques de programmation consistent à ajouter un délai d'expiration afin qu'un navigateur perdu (ou planté ou en boucle) ne fasse pas attendre votre code pour que le document soit terminé même

3
david marcus

Attendez...

D'après mon expérience, vous DEVEZ vous assurer que le DocumCompleted appartient à VOTRE URL et non à une sous-page de cadre, script, image, CSS, etc. Et cela indépendamment du IsBusy ou ReadyState est terminé ou non, ce qui est souvent inexact lorsque la page est légèrement complexe.

Eh bien, c'est ma propre expérience personnelle, sur un programme de travail de VB.2013 et IE11. Permettez-moi également de mentionner que vous devez également prendre en compte le mode de compatibilité IE7 qui est activé par défaut au 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
1
JCM

Dans les événements de chargement, utilisez Me.Hide.

Dans WebBrowser.DocumentCompleted, utilisez Me.Show

1
Landon Tyner

J'ai eu du mal avec ce problème "entièrement chargé" pendant un certain temps, mais j'ai trouvé que la solution suivante fonctionnait pour moi. J'utilise IE7, donc je ne sais pas si cela fonctionne dans d'autres versions, mais ça vaut le coup d'oeil.

J'ai divisé le problème en deux parties; j'avais d'abord besoin d'un message de l'événement DocumentComplete;

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

Ensuite, dans la partie du code où je dois attendre que la page Web soit complètement chargée, j'appelle un autre sous-marin qui fait cela;

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

De plus, je devais également faire la même chose en attendant la fin du code javascript. Par exemple, sur une page lorsque vous sélectionnez un élément dans une liste déroulante html, il remplit la liste déroulante suivante, mais prend du temps pour se révéler. Dans ce cas, j'ai trouvé appeler cela;

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

était suffisant pour contenir le navigateur. Je ne sais pas si cela aidera tout le monde, en tant que combinaison d'IE7, du site Web que je chargeais, et le javascript que la page fonctionnait seule aurait peut-être permis cette solution, mais mérite certainement un essai.

0
Paul Blakeley