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
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
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
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
Techniquement, il y a deux problèmes avec le code publié par BGM:
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".
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
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
Dans les événements de chargement, utilisez Me.Hide
.
Dans WebBrowser.DocumentCompleted, utilisez Me.Show
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.