5

I have a C# form with a web browser control on it.

I am trying to visit different websites in a loop.

However, I can not control URL address to load into my form web browser element.

This is the function I am using for navigating through URL addresses:

public String WebNavigateBrowser(String urlString, WebBrowser wb)
{
    string data = "";
    wb.Navigate(urlString);
    while (wb.ReadyState != WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }
    data = wb.DocumentText;
    return data;
}

How can I make my loop wait until it fully loads?

My loop is something like this:

foreach (string urlAddresses in urls)
{
    WebNavigateBrowser(urlAddresses, webBrowser1);
    // I need to add a code to make webbrowser in Form to wait till it loads
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Val Nolav
  • 908
  • 8
  • 19
  • 44

4 Answers4

9

Add This to your code:

webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);

Fill in this function

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
     //This line is so you only do the event once   
     if (e.Url != webBrowser1.Url) 
        return;


        //do you actual code        



    }
SamFisher83
  • 3,937
  • 9
  • 39
  • 52
  • Sam, I cannot make my code run with your suggestion. It is not working – Val Nolav Mar 19 '12 at 19:45
  • Note the `if` check which is *very* important. `DocumentedCompleted` will fire for each `iframe` as well, for instance. –  Mar 19 '12 at 19:57
  • Did you make sure to change webBrowser1 to wb? – SamFisher83 Mar 19 '12 at 20:06
  • Can you explain what is not working? I know what I posted works with my code. – SamFisher83 Mar 19 '12 at 21:55
  • I need to run that code in a loop because there are numbers of URL. The code really works for the first loop but after the first loop it does not run. I have a HtmlElementCollection in which I am collecting some data out of visited website. In the first loop I can retrieve data for the collection however, in the second loop it does not make my code wait till the web page loads and thus, my collection is null and because of that my click event function does not work properly so the loop breaks. This is my problem. my click event handles if there is NEXT click available. – Val Nolav Mar 20 '12 at 13:47
  • Thank you so much for this URL check! I've been having problems with early DocumentCompleted fires for months and could not figure out why. – Dan Bechard Oct 25 '12 at 15:38
  • Finally a way that really works. My last one (while-loops and delays) was crap as hell. Thanks for this very very very much! – C4d Jun 01 '15 at 12:51
  • This will not fully work if there is complex javascript that builds content after the page load correct? – firebellys Oct 23 '15 at 19:53
6

After some time of anger of the crappy IE functionality I've came across making something which is the most accurate way to judge page loaded complete.

Never use the WebBrowserDocumentCompletedEventHandler event use WebBrowserProgressChangedEventHandler with some modifections seen below.

//"ie" is our web browser object

ie.ProgressChanged += new WebBrowserProgressChangedEventHandler(_ie);
private void _ie(object sender, WebBrowserProgressChangedEventArgs e)
{
  int max = (int)Math.Max(e.MaximumProgress, e.CurrentProgress);
  int min = (int)Math.Min(e.MaximumProgress, e.CurrentProgress);
  if (min.Equals(max))
  {
   //Run your code here when page is actually 100% complete
  }
}

Simple genius method of going about this, I found this question googling "How to sleep web browser or put to pause"

user2887749
  • 79
  • 1
  • 2
  • 8
  • Well... This did not help me with my javascript complete issue. :( – Omzig Apr 30 '14 at 18:37
  • Confirming: this solution is not absolute. For example, this triggers for me 5 times, while `DocumentCompleted` only 2 times... So, that eternal question `"how to know when WB really finished loading document"` is still open. – Kosmo零 Nov 30 '17 at 07:04
1

According to MSDN (contains sample source) you can use the DocumentCompleted event for that. Additional very helpful information and source that shows how to differentiate between event invocations can be found here.

Community
  • 1
  • 1
Yahia
  • 69,653
  • 9
  • 115
  • 144
  • 1
    In practice it doesn't work. When I did it myself it triggers around 4-5 times for each Document. – Haedrian Mar 19 '12 at 19:23
  • 1
    @Haedrian it does work... it is called for every document that completes which means that it can be called several times for one URL (for example when it contains IFRAMEs or uses AJAX or works with redirections etc.). Follow the second link to see a suggestion on how to differentiate between these occurences... – Yahia Mar 19 '12 at 19:25
0

what you experiencend happened to me . readyStete.complete doesnt work in some cases. here i used bool in document_completed to check state

 button1_click(){
    //go site1 
    wb.Navigate("site1.com");
    //wait for documentCompleted before  continue to  execute  any further 
    waitWebBrowserToComplete(wb); 

    // set some values in html page
    wb.Document.GetElementById("input1").SetAttribute("Value", "hello");
    //  then click submit. (submit does navigation)
    wb.Document.GetElementById("formid").InvokeMember("submit");
    // then wait for doc complete        
    waitWebBrowserToComplete(wb);


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

// helpers
//instead of checking  readState . we get state from DocumentCompleted Event via bool value
bool webbrowserDocumentCompleted = false;
public static void waitWebBrowserToComplete(WebBrowser wb)
{
  while (!webbrowserDocumentCompleted )
      Application.DoEvents();
  webbrowserDocumentCompleted = false;
}

form_load(){
  wb.DocumentCompleted += (o, e) => {
     webbrowserDocumentCompleted = true;
  };
}
bh_earth0
  • 2,537
  • 22
  • 24