12

.NET WebBrowser コントロールを使用しています。Web ページが完全にロードされたことを知るにはどうすればよいですか?

ブラウザがデータをフェッチしなくなったときを知りたいです。(IE のステータス バーに「完了」と表示された瞬間...)。

ノート:

  • DocumentComplete/NavigateComplete イベントは、複数のフレームを含む Web サイトで複数回発生する場合があります。
  • ブラウザの準備完了状態でも問題は解決しません。
  • フレーム コレクション内のフレーム数を確認してから、DocumentComplete イベントを取得した回数を数えてみましたが、これも機能しません。
  • this.WebBrowser.IsBusy も機能しません。Document Complete ハンドラーでチェックすると、常に「false」になります。
4

12 に答える 12

3

アプリケーションで問題を解決した方法は次のとおりです。

private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    if (e.Url != wbPost.Url)
        return;
    /* Document now loaded */
}
于 2010-02-24T21:26:27.577 に答える
2

これが私のテスト済みバージョンです。これを自分のものにして、一度DocumentCompleted Event Handlerだけ呼び出したいコードをメソッドに配置するだけです。事実上、このアプローチは、ページが 200 ミリ秒の間安定していた時期を判断してから、その処理を実行します。OnWebpageReallyLoaded()

// 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 */
}
于 2010-04-13T14:28:11.303 に答える
2

ページが完全に読み込まれたとき(フレームを含む) に何かを行うための私のアプローチは、次のようなものです。

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;
    }

私の他のアプローチから、いくつかの「してはいけない」ことを学びました。

  • スプーンを曲げないでください... ;-)
  • DocumentComplete、Frames、HtmlWindow.Load イベントを使用して複雑な構造を構築しようとしないでください。まったく機能する場合、ソリューションは脆弱になります。
  • System.Timers.Timerの代わりに使用しないWindows.Forms.Timerでください。使用すると、アプリの残りの部分とは異なるスレッドでタイマーが実行されているため、奇妙なエラーが奇妙な場所で発生し始めます。
  • DocumentComplete なしでタイマーだけを使用しないでください。ページの読み込みが開始される前にタイマーが起動し、コードが途中で実行される可能性があります。
于 2010-01-31T17:22:48.123 に答える
0

webBrowser.StatusTextメソッドを使用します。「完了」と表示されると、すべてが読み込まれます。それとも私は何かが足りないのですか?

于 2010-03-30T20:54:38.577 に答える
0

各フレームでjavascriptを使用して、フレームが完了したときにフラグを設定し、C#でフラグを確認するのはどうですか?

于 2009-03-23T13:33:40.153 に答える
0

これが最終的に私のために働いたものです:

       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;
        }
    }

各ドキュメント完了イベントで、すべてのhtml要素を実行し、使用可能なすべてのフレームを確認します(最適化できることはわかっています)。フレームごとに、準備完了状態を確認します。かなり信頼性がありますが、jeffamaphoneが言ったように、内部更新をトリガーするサイトをすでに見ました。しかし、上記のコードは私のニーズを満たしています。

編集:すべてのフレームにフレームを含めることができるので、このコードを更新して、すべてのフレームの状態を再帰的にチェックする必要があると思います。

于 2009-03-26T10:12:10.987 に答える
0

各フレームだけでなく、外部WebページのBeforeNavigateイベントとDocumentCompleteイベントを取得します。外側のWebページのDocumentCompleteイベントを取得すると、完了したことがわかります。これを決定するには、 IWebBrowser2 :: TopLevelContainer()のマネージド等価物を使用できるはずです。

ただし、Webサイト自体は、必要なときにいつでもより多くのフレームナビゲーションをトリガーできるため、ページが本当に永久に実行されるかどうかはわかりません。最善の方法は、表示されるすべてのBeforeNavigateのカウントを保持し、DocumentCompleteを取得したときにカウントをデクリメントすることです。

編集:これが管理されたドキュメントです:TopLevelContainer

于 2009-03-26T07:39:11.087 に答える
0

WebBrowser.IsBusyプロパティを試しましたか?

于 2009-03-23T13:11:49.830 に答える
0

代替手段はありませんが、Document Complete ハンドラー中のIsBusyプロパティtrueは、ハンドラーがまだ実行中であり、したがってWebBrowserコントロールが技術的にまだ「ビジー」であるためではないかと思います。

IsBusy最も簡単な解決策は、フラグがリセットされるまで約 100 ミリ秒ごとに実行されるループを持つことです (エラーの場合は最大実行時間)。もちろん、ページの読み込み中のどの時点でもIsBusyに設定されないことを前提としています。false

Document Complete ハンドラが別のスレッドで実行される場合は、ロックを使用してメイン スレッドをスリープ状態にし、Document Complete スレッドから復帰させることができます。次に、IsBusyフラグを確認し、メイン スレッドを再ロックしますtrue

于 2009-03-23T13:45:52.137 に答える
0

jQueryは使えますか?次に、ターゲット フレームにフレーム準備完了イベントを簡単にバインドできます。道順については、この回答を参照してください。このブログ投稿にもそれに関する議論があります。最後に、使用できるプラグインがあります。

アイデアは、次を使用して Web ページのフレーム数をカウントすることです。

$("iframe").size()

次に、iframe の準備完了イベントが発生した回数をカウントします。

于 2009-03-26T07:35:30.440 に答える
0

IE.readyState = READYSTATE_COMPLETE のチェックは機能するはずですが、それが信頼できると証明されず、文字通り「IEがステータスバーに「完了」を書き込む瞬間」を知りたい場合は、IE.StatusTextが含まれるまでループを実行できます"終わり"。

于 2011-11-03T04:10:39.007 に答える
0

うまくいくかどうかわかりませんが、次のようにフレームセットに JavaScript の「onload」イベントを追加してみてください。

function everythingIsLoaded() { alert("everything is loaded"); }
var frameset = document.getElementById("idOfYourFrameset");
if (frameset.addEventListener)
    frameset.addEventListener('load',everythingIsLoaded,false); 
else
    frameset.attachEvent('onload',everythingIsLoaded); 
于 2009-03-25T15:22:37.503 に答える