Frage

Ich verwende .NET WebBrowser-Steuerelement. Wie kann ich wissen, wenn eine Web-Seite vollständig geladen ist?

Ich möchte wissen, wenn der Browser keine weiteren Daten abruft. (In dem Moment, wenn IE schreibt 'Fertig' in seiner Statusleiste ...).

Weitere Informationen:

  • Die Document / NavigateComplete Ereignisse können mehrmals für eine Website mit mehreren Frames auftreten.
  • Der Browser bereit Zustand löst nicht das Problem.
  • Ich habe versucht, die Anzahl der Frames in der Frame Sammlung prüft und dann die Anzahl der oft ich DocumentComplete' Ereignis bekommen, aber das funktioniert auch nicht.
  • this.WebBrowser.IsBusy funktioniert auch nicht. Es ist immer ‚falsch‘, wenn es in dem Dokument der kompletten Handler zu überprüfen.
War es hilfreich?

Lösung 4

Hier ist, was für mich endlich geklappt:

       public bool WebPageLoaded
    {
        get
        {
            if (this.WebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
                return false;

            if (this.HtmlDomDocument == null)
                return false;

            // iterate over all the Html elements. Find all frame elements and check their ready state
            foreach (IHTMLDOMNode node in this.HtmlDomDocument.all)
            {
                IHTMLFrameBase2 frame = node as IHTMLFrameBase2;
                if (frame != null)
                {
                    if (!frame.readyState.Equals("complete", StringComparison.OrdinalIgnoreCase))
                        return false;

                }
            }

            Debug.Print(this.Name + " - I think it's loaded");
            return true;
        }
    }

Auf jedem Dokument komplette Veranstaltung, die ich über die ganze HTML-Element laufen und prüfen Sie alle Rahmen zur Verfügung (ich weiß, es optimiert werden kann). Für jeden Rahmen prüfe ich seinen Bereitschaftszustand. Es ist ziemlich zuverlässig, aber genau wie jeffamaphone sagte ich bereits Seiten gesehen, dass einige interne Auffrischungen ausgelöst. Aber der obige Code erfüllt meine Bedürfnisse.

Edit:. Jeder Rahmen kann in ihm enthalten Frames so denke ich, dieser Code sollte rekursiv aktualisiert werden, um den Zustand jedes Rahmens zu überprüfen

Andere Tipps

Mein Ansatz etwas zu tun, wenn Seite vollständig geladen ist (inklusive Rahmen) ist so etwas wie folgt aus:

using System.Windows.Forms;
    protected delegate void Procedure();
    private void executeAfterLoadingComplete(Procedure doNext) {
        WebBrowserDocumentCompletedEventHandler handler = null;
        handler = delegate(object o, WebBrowserDocumentCompletedEventArgs e)
        {
            ie.DocumentCompleted -= handler;
            Timer timer = new Timer();
            EventHandler checker = delegate(object o1, EventArgs e1)
            {
                if (WebBrowserReadyState.Complete == ie.ReadyState)
                {
                    timer.Dispose();
                    doNext();
                }
            };
            timer.Tick += checker;
            timer.Interval = 200;
            timer.Start();
        };
        ie.DocumentCompleted += handler;
    }

Aus meinen anderen Ansätzen habe ich gelernt, einig „nicht“ es:

  • versuchen Sie nicht den Löffel zu biegen ...; -)
  • versuchen Sie nicht, aufwendiges Konstrukt zu bauen mit Document, Rahmen, HtmlWindow.Load Veranstaltungen. Ihre Lösung wird brüchig, wenn überhaupt arbeiten.
  • verwendet nicht System.Timers.Timer statt Windows.Forms.Timer, wird seltsame Fehler beginnen in fremden Orten auftreten, wenn Sie das tun, aufgrund Timer auf anderen Thread ausgeführt wird, dass der Rest Ihrer Anwendung.
  • verwenden nicht nur Timer ohne DocumentComplete', weil es Feuer kann, bevor Sie Ihre Seite selbst zu laden beginnt und wird Ihr Code vorzeitig auszuführen.

Hier ist, wie ich das Problem in meiner Anwendung gelöst:

private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    if (e.Url != wbPost.Url)
        return;
    /* Document now loaded */
}

Hier ist meine Version getestet. machen dies einfach Ihre DocumentCompleted Event Handler und legen Sie den Code, den Sie nur aufgerufen werden sollen einmal in das Verfahren OnWebpageReallyLoaded(). Effektiv dieser Ansatz bestimmt, wann die Seite für 200ms stabil war und dann tut seine Sache.

// event handler for when a document (or frame) has completed its download
Timer m_pageHasntChangedTimer = null;
private void webBrowser_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e ) {
    // dynamic pages will often be loaded in parts e.g. multiple frames
    // need to check the page has remained static for a while before safely saying it is 'loaded'
    // use a timer to do this

    // destroy the old timer if it exists
    if ( m_pageHasntChangedTimer != null ) {
        m_pageHasntChangedTimer.Dispose();
    }

    // create a new timer which calls the 'OnWebpageReallyLoaded' method after 200ms
    // if additional frame or content is downloads in the meantime, this timer will be destroyed
    // and the process repeated
    m_pageHasntChangedTimer = new Timer();
    EventHandler checker = delegate( object o1, EventArgs e1 ) {
        // only if the page has been stable for 200ms already
        // check the official browser state flag, (euphemistically called) 'Ready'
        // and call our 'OnWebpageReallyLoaded' method
        if ( WebBrowserReadyState.Complete == webBrowser.ReadyState ) {
            m_pageHasntChangedTimer.Dispose();
            OnWebpageReallyLoaded();
        }
    };
    m_pageHasntChangedTimer.Tick += checker;
    m_pageHasntChangedTimer.Interval = 200;
    m_pageHasntChangedTimer.Start();
}

OnWebpageReallyLoaded() {
    /* place your harvester code here */
}

Wie wäre es in jedem Rahmen mit Hilfe von Javascript ein Flag zu setzen, wenn der Rahmen vollständig ist, und haben dann C # Blick auf die Fahnen?

Ich habe eine Alternative nicht für Sie, aber ich frage mich, ob die IsBusy Eigenschaft ist true während des Dokuments vollständig Handler ist, da der Handler noch läuft und damit die WebBrowser Kontrolle ist technisch noch ‚beschäftigt‘.

Die einfachste Lösung wäre es, um eine Schleife zu haben, der alle 100 ms oder so, bis der IsBusy Flag (mit max Ausführungszeit von Fehlern für den Fall) zurückgesetzt ausführt. Das setzt natürlich voraus, dass IsBusy nicht an jedem Punkt während des Ladens der Seite false eingestellt wird.

Wenn das Dokument komplett Handler auf einem anderen Thread ausgeführt wird, können Sie eine Sperre verwenden könnte Ihr Haupt-Thread zu senden, es zu schlafen und aufwachen aus dem Dokument vollständig Faden wieder auf. Dann überprüfen die IsBusy Flag, Wieder Arretieren des Haupt-Thread seine noch true.

Ich bin mir nicht sicher, dass es funktioniert, aber versuchen, einen JavaScript „onload“ -Ereignis auf Ihrem Frameset so hinzuzufügen:

function everythingIsLoaded() { alert("everything is loaded"); }
var frameset = document.getElementById("idOfYourFrameset");
if (frameset.addEventListener)
    frameset.addEventListener('load',everythingIsLoaded,false); 
else
    frameset.attachEvent('onload',everythingIsLoaded); 

Können Sie jQuery verwenden? Dann könnten Sie leicht Rahmen bereit Ereignisse auf dem Zielrahmen binden. Siehe diese Richtungen beantworten. Diese Blog-Post hat auch eine Diskussion darüber. Schließlich gibt es eine Plug-in , die Sie verwenden können.

Die Idee ist, dass Sie die Anzahl der Bilder auf der Webseite zählen mit:

$("iframe").size()

und dann zählen Sie, wie oft die iframe bereit Ereignis ausgelöst wurde.

Sie erhalten eine BeforeNavigate und Document Ereignis für die äußere Webseite, sowie jeden Rahmen erhalten. Du weißt, du bist fertig, wenn Sie das Document Ereignis für die äußeree Homepage zu erhalten. Sie sollten das verwaltete equivilent von IWebBrowser2 :: nutzen können TopLevelContainer () diese zu bestimmen.

Hüten Sie sich vor, jedoch kann die Website selbst mehr Frames navigiert jederzeit auslösen es will, so dass Sie nie wissen, ob eine Seite wirklich für immer getan wird. Das Beste, was Sie tun können, ist halten eine Zählung aller BeforeNavigates Sie sehen und verringern die Zählung, wenn Sie ein Document bekommen.

Edit: Hier ist die verwalteten Dokumente: TopLevelContainer .

Ich verwende nur die webBrowser.StatusText Methode. Wenn es sagt: „Fertig“ alles geladen ist! Oder bin ich etwas fehlt?

Überprüfen auf IE.readyState = READYSTATE_COMPLETE sollte funktionieren, aber wenn das beweist nicht für Sie zuverlässig und Sie buchstäblich wollen „um den Moment, in dem IE in seiner Statusleiste auf‚Fertig‘, schreibt“ kennen, dann können Sie eine Schleife tun, bis IE .StatusText enthält "Fertig".

Haben Sie WebBrowser.IsBusy Eigenschaft versucht?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top