web-dev-qa-db-fra.com

C # comment attendre la fin du chargement d'une page Web avant de continuer

J'essaie de créer un programme pour cloner plusieurs bogues à la fois via l'interface Web de notre système de suivi des défauts. Comment puis-je attendre avant qu'une page soit complètement chargée avant de continuer?

//This is pseudo code, but this should give you an idea of what I'm trying to do.  The
//actual code uses multi-threading and all that good stuff :).
foreach (string bug in bugs)
{
    webBrowser.Navigate(new Uri(url));
    webBrowser.Document.GetElementById("product").SetAttribute("value", product);
    webBrowser.Document.GetElementById("version").SetAttribute("value", version);
    webBrowser.Document.GetElementById("commit").InvokeMember("click");

    //Need code to wait for page to load before continuing.
}
26
MD6380

Essayez l'événement DocumentCompleted

webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);

void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    webBrowser.Document.GetElementById("product").SetAttribute("value", product);
    webBrowser.Document.GetElementById("version").SetAttribute("value", version);
    webBrowser.Document.GetElementById("commit").InvokeMember("click");
}
27
Quintin Robinson

Ce code m'a été très utile. Peut-être que ça pourrait aussi être pour toi

wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
     Application.DoEvents();
}
MessageBox.Show("Loaded");
31
Yura

La meilleure façon de le faire sans bloquer le thread d'interface utilisateur est d'utiliser Async et Await introduits dans .net 4.5.
Vous pouvez coller ceci dans votre code, changez simplement le navigateur en nom de navigateur Web. De cette façon, votre thread attend la page à charger, si elle ne fonctionne pas à temps, elle cesse d'attendre et votre code continue de s'exécuter:

private async Task PageLoad(int TimeOut)
    {
        TaskCompletionSource<bool> PageLoaded = null;
        PageLoaded = new TaskCompletionSource<bool>();
        int TimeElapsed = 0;
        Browser.DocumentCompleted += (s, e) =>
        {
            if (Browser.ReadyState != WebBrowserReadyState.Complete) return;
            if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult(true);
        };
        //
        while (PageLoaded.Task.Status != TaskStatus.RanToCompletion)
        {
            await Task.Delay(10);//interval of 10 ms worked good for me
            TimeElapsed++;
            if (TimeElapsed >= TimeOut * 100) PageLoaded.TrySetResult(true);
        }
    }

Et vous pouvez l'utiliser comme ceci, avec une méthode asynchrone ou un événement de clic de bouton, faites-le simplement async:

private async void Button1_Click(object sender, EventArgs e)
{
   Browser.Navigate("www.example.com");
   await PageLoad(10);//await for page to load, timeout 10 seconds.
   //your code will run after the page loaded or timeout.
}
19
YıldızGezen

Découvrez le projet WatiN :

Inspiré par Watir , le développement de WatiN a commencé en décembre 2005 pour rendre possible un type similaire de test d'application Web pour les langages .Net. Depuis lors, WatiN est devenu un framework facile à utiliser, riche en fonctionnalités et stable. WatiN est développé en C # et vise à vous apporter un moyen simple d'automatiser vos tests avec Internet Explorer et FireFox en utilisant .Net ...

12
Charlino

La méthode de tâche a fonctionné pour moi, sauf que Browser.Task.IsCompleted doit être remplacé par PageLoaded.Task.IsCompleted.

Désolé, je n'ai pas ajouté de commentaire, car j'ai besoin d'une réputation plus élevée pour ajouter des commentaires.

8
Vlad K

le code yuna et bnl a échoué dans le cas ci-dessous;

exemple manquant:

Le 1er attend la fin. Mais le 2ème avec le membre invokem ("soumettre") ne l'a pas fait. invoquer des œuvres. mais ReadyState.Complete agit comme son Completed avant sa VRAIMENT terminée:

wb.Navigate(url);
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
   Application.DoEvents();
}
MessageBox.Show("ok this waits Complete");

//navigates to new page
wb.Document.GetElementById("formId").InvokeMember("submit");
while(wb.ReadyState != WebBrowserReadyState.Complete)
{
   Application.DoEvents();
}
MessageBox.Show("webBrowser havent navigated  yet. it gave me previous page's html.");  
var html = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;

comment corriger cette situation indésirable:

usage

    public myForm1 {

        myForm1_load() { }

        // func to make browser wait is inside the Extended class More tidy.
        WebBrowserEX wbEX = new WebBrowserEX();

        button1_click(){
            wbEX.Navigate("site1.com");
            wbEX.waitWebBrowserToComplete(wb);

            wbEX.Document.GetElementById("input1").SetAttribute("Value", "hello");
            //submit does navigation
            wbEX.Document.GetElementById("formid").InvokeMember("submit");
            wbEX.waitWebBrowserToComplete(wb);
            // this actually waits for document Compelete. worked for me.

            var processedHtml = wbEX.Document.GetElementsByTagName("HTML")[0].OuterHtml;
            var rawHtml = wbEX.DocumentText;
         }
     }

//put this  extended class in your code.
//(ie right below form class, or seperate cs file doesnt matter)
public class WebBrowserEX : WebBrowser
{
   //ctor
   WebBrowserEX()
   {
     //wired aumatically here. we dont need to worry our sweet brain.
     this.DocumentCompleted += (o, e) => { webbrowserDocumentCompleted = true;};
   }
     //instead of checking  readState, get state from DocumentCompleted Event 
     // via bool value
     bool webbrowserDocumentCompleted = false;
     public void waitWebBrowserToComplete()
     {
       while (!webbrowserDocumentCompleted )
       { Application.DoEvents();  }
       webbrowserDocumentCompleted = false;
     }

 }
4
bh_earth0

Essayez Selenium ( http://seleniumhq.org ) ou WatiN ( http://watin.sourceforge.net ) pour vous épargner du travail.

2
PHeiberg
while (true)
        {//ie is the WebBrowser object
            if (ie.ReadyState == tagREADYSTATE.READYSTATE_COMPLETE)
            {
                break;
            }
            Thread.Sleep(500);
        }

J'ai utilisé cette méthode pour attendre le chargement de la page.

1
Gokul

Si vous utilisez l'objet COM InternetExplorer.Application, vérifiez la propriété ReadyState pour la valeur 4.

1
James Pogran

Je pense que l'événement DocumentCompleted du contrôle WebBrowser devrait vous amener là où vous devez aller.

1
Mike

En supposant que l'élément "commit" représente un bouton d'envoi de formulaire standard, vous pouvez attacher un gestionnaire d'événements à l'événement WebBrowsers Navigated.

1
AnthonyWJones