2009-03-23 12 views
11

.NET WebBrowserコントロールを使用しています。 ウェブページが完全にロードされたことを知る方法を教えてください。HTML - すべてのフレームがロードされたことをどのように知るのですか?

ブラウザがそれ以上のデータを取得していないことを知りたい場合。 (IEがステータスバーに「完了」と書いた瞬間...)。

注:

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

答えて

1

は最終的に私のために働いていたものです:

各ドキュメントの完全なイベントで
 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と同じように、私はすでに内部リフレッシュを引き起こしたサイトを見ています。 しかし、上記のコードは私のニーズを満たしています。

編集:すべてのフレームにフレームが含まれている可能性があるので、このコードはすべてのフレームの状態を再帰的にチェックするように更新する必要があります。

0

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

+1

ドキュメント完了ハンドラが呼び出されるたびに、Webブラウザはビジーではないと主張します。 –

0

フレームが完了したらフラグを設定するために各フレームでjavascriptを使用して、C#でフラグを確認する方法はありますか?ハンドラがまだ実行されているので、WebBrowserコントロールは、まだ技術的には「忙しい」ですので、私はあなたのための選択肢を持っていないが、IsBusyプロパティはドキュメントの完全なハンドラ中にtru電子であることかしら

+0

ブラウザがナビゲートしているすべてのサイトのDOMツリーを操作したくありません。しかし、私はあなたのソリューションを使用して、私はどのようにjavascriptでそれを行うのですか? –

+0

私はJS対C#でこれを行う利点が表示されません。 –

0

です。

最も簡単な解決策は、IsBusyフラグがリセットされるまで(エラーの場合は最大実行時間を指定して)、100ミリ秒ごとに実行されるループを作成することです。当然のことながら、IsBusyは、ページロード中のどの時点でもfalseに設定されません。

ドキュメントコンプリートハンドラが別のスレッドで実行される場合は、ロックを使用してメインスレッドをスリープ状態にし、ドキュメント完了スレッドから起動することができます。その後、IsBusyフラグをチェックして、メインスレッドを再ロックすることはまだそれがtrueであることを確認してください。

+0

しかし、IsBusyはあまりに早くfalseに設定されています。たとえば、Webページに6つのフレームがある場合、最初のフレームの読み込みが完了すると、DocumentCompleteイベントでIsBusyはfalseになります。 –

+0

各フレームには独自のWebブラウザ(IWebBrowser2実装)が用意されています。 IsBusy属性は、特定のフレームにのみ適用される可能性があります。それが完了すると、もはやビジーではありません。 –

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); 
+0

すべてのフレームがすべてのWebサイトにロードされているかどうかを知りたいので、どのフレームに含まれているか分かりません。 –

+0

各フレームではなく、フレームセット(すべてのフレームの親)で行う必要があります。そのようなWebサイトから取得するのはかなり簡単です:document.getElementsByTagName( 'frameset')[0] – paulgreg

0

あなたはjQueryのを使用することはできますか?そうすれば、フレーム準備イベントをターゲットフレームに簡単にバインドできます。行き方はthisの回答をご覧ください。このblog postにもディスカッションがあります。最後に、使用できるplug-inがあります。

アイデアは、あなたが使用してWebページ内のフレームの数を数えることである:

$("iframe").size() 

をして、あなたはインラインフレームreadyイベントが発射された回数をカウントします。

0

外部Webページと各フレームのBeforeNavigateイベントとDocumentCompleteイベントが表示されます。外部WebページのDocumentCompleteイベントを取得すると、完了したことがわかります。これを確認するには、IWebBrowser2::TopLevelContainer()という管理対象の品種を使用することができます。

しかし、ウェブサイト自体が望むときはいつでもより多くのフレームナビゲーションをトリガできるので、ページが本当に永遠に完了したかどうかはわかりません。あなたが行うことができる最善のことは、BeforeNavigatesのすべてを数え続けて、DocumentCompleteを取得したときにカウントを表示したり減らしたりすることです。

編集:管理対象のドキュメントはTopLevelContainerです。ここで

+1

WebBrowserコントロール内でドキュメントをナビゲートする前にカウントしてみました。それは同期されていません... :(。ドキュメントが完了するよりもナビゲートする前に多くのことがあります[キャッシュされたフレームやフェッチされたフレームを複製することがあるかもしれません]。 –

+0

ドキュメント完了イベントについて:C# –

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

私はいくつかの「んではない」-sを学びました

  • スプーンを曲げようとしないでください... ;-)
  • DocumentComplete、Frames、HtmlWindow.Loadイベントを使用して精巧な構造を構築しようとしないでください。あなたのソリューションは、まったく働くと壊れやすいでしょう。
  • Windows.Forms.Timerの代わりにSystem.Timers.Timerを使用しないと、アプリの残りのスレッドとは別のスレッドで実行されているタイマーのために、奇妙なエラーが発生しやすくなります。
  • DocumentCompleteを使用しないTimerは、ページが読み込まれる前に起動し、コードを途中で実行する可能性があるため、Timerを使用しないでください。ここで
2

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

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

ナビゲーションバーのクリックなどをして、新しいWebサイトが再読み込みされるようにする場合は、Webブラウザを使用して読み込みが完了したドキュメントオブジェクトを取得することはできません。 –

0

私はちょうどwebBrowser.StatusTextメソッドを使用します。 「完了」と表示されたら、すべてがロードされます! 何か不足していますか?

+0

iframeがある場合は否定 –

2

私のテスト済みのバージョンです。これをあなたのDocumentCompleted Event Handlerにして、としたいコードをOnWebpageReallyLoaded()に一度置きます。効果的に、このアプローチは、ページが200msの間安定していたかどうかを判断し、その後そのことを行います。

// 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 */ 
} 
+0

多くのありがとう!私は完璧に働いています。 – selegnasol

0

IE.readyState = READYSTATE_COMPLETEが動作するはずのチェックが、それはあなたのための信頼性の証明ではないですし、あなたは文字通り、あなたが行うことができ、「IEがそのステータスバーに 『完了』の書き込みの瞬間」を知りたい場合はIE.StatusTextに "Done"が含まれるまでのループ。