1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

C# click on button using Xpath

Discussion in 'C, C++, C#' started by mrwho, Apr 8, 2010.

  1. mrwho

    mrwho Junior Member

    Joined:
    Apr 3, 2008
    Messages:
    122
    Likes Received:
    39
    I'm using the webBrowser controls to go to a site, search for a string and if found clicks a Accept button. However there's multiple Accept buttons down the page.
    I used firebug to get the Xpath of the 1st buttons and here's what the Xpath looks like:
    Code:
    /html/body/table[2]/tbody/tr[2]/td/table/tbody/tr/td[3]/table/tbody/tr/td/table[2]/tbody/tr[3]/td/table/tbody/tr[2]/td/button
    2nd button Xpath looks like this:
    Code:
    /html/body/table[2]/tbody/tr[2]/td/table/tbody/tr/td[3]/table/tbody/tr/td/table[2]/tbody/tr[3]/td/table/tbody/tr[3]/td/button
    is there anyway to click a button using the Xpath?
     
  2. mappum

    mappum Registered Member

    Joined:
    Aug 8, 2009
    Messages:
    84
    Likes Received:
    11
    Location:
    At my computer... how else would I be on a forum?
    Are you using the WebBrowser because you need it to execute JavaScript or something? It is much faster, easier and more stable to just have your program send the http data (POST/GET) and store the response.

    Try using WireShark to see when it is using POST requests, or use the FireFox addon Tamper Data to see what is being POSTed.
     
  3. mrwho

    mrwho Junior Member

    Joined:
    Apr 3, 2008
    Messages:
    122
    Likes Received:
    39
    yes using the webBrowser is necessary for me because other people will be using this and want to see the visual side of things...
    I can tell "on button click" the value changes every time to a url with a random number attached and the next button below is the same way except its random number will be the next higher up number from the button before it
     
  4. underplay

    underplay Newbie

    Joined:
    Jan 13, 2009
    Messages:
    27
    Likes Received:
    1
    mappum is correct, if your doing a single call or request, there is nothing wrong with webbrowser, but if your doing multiple requetsts and performance is an issue, its better to use code thats not tied into the WebBrowser control, this has serious performance issunes in memory and processing times.

    As for the xpath, you want to remove tbody, its something that firedebug picks up but from my experience the parsers in C# wont detect the tbody. It takes alot of fiddling around at first to understand the differences between firedebug's xpath and the way the C# libraries/control's handle them. Good luck.
     
  5. ShiftySituation

    ShiftySituation Power Member

    Joined:
    Apr 15, 2010
    Messages:
    621
    Likes Received:
    314
    Occupation:
    Having fun
    Location:
    Jacksonville, FL
    You can loop through all of the HtmlElements for buttons, if it is always the first button you need to click then use HtmlElement.InvokeMember("Click"); Break; in the first loop.

    If the button has an ID that no other buttons have, then you can getElementByID("IDNAME") and then InvokeMember("Click");
     
    Last edited: Apr 22, 2010
  6. mrwho

    mrwho Junior Member

    Joined:
    Apr 3, 2008
    Messages:
    122
    Likes Received:
    39
    underplay another problem I encountered when using http requests is that I can't login into the site using network credentials and using google to find a solution to this issue the login may require form authentication. Unless I can use the webBrowser first to login and then pass the cookies and stuff to http requests I'll have to stick to the webBrowser.

    ShiftySituation I have working code that can click on the 1st or last button but still dont have a way to click on the buttons in the middle. here's the code for it:
    Code:
     var buttonControls = (from HtmlElement element in webBrowser1.Document.GetElementsByTagName("button") select element).ToList();
                HtmlElement submitButton = buttonControls.FirstOrDefault(x => x.InnerText == "Accept");
                if (submitButton != null)
                {
                    submitButton.InvokeMember("click");
                }
                else
                {
                    //didn't find it
                }
     
  7. ShiftySituation

    ShiftySituation Power Member

    Joined:
    Apr 15, 2010
    Messages:
    621
    Likes Received:
    314
    Occupation:
    Having fun
    Location:
    Jacksonville, FL
    If you want to move to the HttpWebRequest you don't use credentials in the way you are thinking. There is only a select few cases where using credentials will work and in your case you probably aren't going to run into it. On that note, the only place I can recall using credentials is when using WebProxy to set a proxy IP, port and login/pass (credentials) if needed. You will most likely want to use a POST string to log into the site. Which if you run Fiddler, log into the site that you want, it will show you all of the info that is sent to the server so you can mimic that information using HttpWebRequest.

    Easy way to get login cookies so you don't have to log in with a POST string, you can log into the site with IE and then grab the info from the cookie.txt that is saved to your hard drive, figure out how it is seperated and then use something like:

    Code:
                        CookieContainer thisCookie = new CookieContainer();
                        Cookie addCookie = new Cookie();
                        addCookie.Name = name;
                        addCookie.Value = value;
                        addCookie.Expires = DateTime.Now.AddDays(30);
                        addCookie.Domain = ".whatever.com";
                        addCookie.Path = "/";
     
                        thisCookie.Add(addCookie);
    Now as far as using HtmlElement, you can loop through each one like:
    Code:
    HtmlElement elements = webBrowser1.Document.GetElementsByTagName("button");
    foreach (HtmlElement elem in elements)
    {
    elem.InvokeMember("click");
    }
    
    My syntax might me off but that will click every button. Now you can just control it with setting an int and just increment it every time it loops and if it gets to a number you specify then click. Example:

    Code:
    HtmlElement elements = webBrowser1.Document.GetElementsByTagName("button");
    
    int click = 5; //because I want to click the 5th button
    int i = 1;
    foreach (HtmlElement elem in elements)
    {
      if (i = click)
       {
         elem.InvokeMember("click");
         break;
       }
      i++;
    }
    
    Again, my syntax could be a bit off but should lead you in the right direction.