I have a WebBrowser inside a form and I want to do some automation with it. I click a button inside a windows form that commands the Navigate method of the WebBrowser to a certain page. Then I automatically click a link after DocumentCompleted has fired but after that I want to also click a Button that exists in the new page that appeared by clicking the link. It seems DocumentCompleted fires only when I click the button in the windows form not when I automatically click the a link inside the webpage.
void BtnTestClick(object sender, EventArgs e)
{
webBrowser1.Navigate(#"https://play.google.com/apps/");
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
}
public void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = sender as WebBrowser;
//webBrowser.DocumentCompleted -= WebBrowser_DocumentCompleted;
// test to see if we're on fist CONFIRM page then go forward by clicking
var links = webBrowser1.Document.GetElementsByTagName("a");
foreach (HtmlElement link in links)
{
if (link.InnerText == "Proceed anyway")
{
link.InvokeMember("click");
}
} // this works
webBrowser1.Document.GetElementById("gwt-uid-126").InvokeMember("click");
}
After the link.InvokeMember("click"); a new page loads in the webbrowser that has a button which I also want to click ( gwt-uid-126 )
But it doesn't get clicked.
I've also tried:
var elements = webBrowser1.Document.GetElementsByTagName("button");
foreach (HtmlElement file in elements)
{
if (file.GetAttribute("class") == "GKYRWGTDNX GKYRWGTDLY")
{
file.Focus();
file.InvokeMember("click");
}
}
With no luck!
From what I see, second click doesn't work because the document is not completely loaded and second click is invoked.
You will have to add another if-else block that handled second document load.
Edit1: I was on phone when I answered this, so couldn't provide any snippet. Following is the change that you can do WebBrowser_DocumentCompleted method.
var links = webBrowser1.Document.GetElementsByTagName("a");
foreach (HtmlElement link in links)
{
if (link.InnerText == "Proceed anyway")
{
link.InvokeMember("click");
}
}
// following is for the page that is loaded on click of link.
var gwt_uid_126 = webBrowser1.Document.GetElementById("gwt-uid-126");
if(gwt_uid_126 != null)
{
gwt_uid_126.InvokeMember("click");
}
You might want to check if the WebBrowser_DocumentCompleted method is actually being called on second page load. This might be the reason why second click is not registering.
move this part of code in the Constructor or Form_Load:
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
try this instead of using WebBrowserDocumnetCompletedEventHandler:
void btnTestClick(object sender, EventArgs e)
{
webBrowser1.Navigate(#"https://www.google.com/");
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
continue;
var webBrowser = sender as WebBrowser;
//webBrowser.DocumentCompleted -= WebBrowser_DocumentCompleted;
// test to see if we're on fist CONFIRM page then go forward by clicking
var links = webBrowser1.Document.GetElementsByTagName("a");
foreach (HtmlElement link in links)
{
if (link.InnerText == "Proceed anyway")
{
link.InvokeMember("click");
}
} // this works
webBrowser1.Document.GetElementById("gwt-uid-126").InvokeMember("click");
}
Related
I am using C# to login to a local web page.
I am using webBrowser in order to display the page after the log.
First, I navigate to page then I fill the username & password then I invoke a click.The element to be clicked is recognized; so I assume that the click happened. But the result page isn't showing, nothing appears when I execute.
I tried this:
public WebBrowser webBrowser;
public MainWindow()
{
InitializeComponent();
webBrowser = new WebBrowser();
webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(LoginEvent);
webBrowser.AllowNavigation = true;
webBrowser.Navigate("http://192.168.1.100/login.html");
}
private void LoginEvent(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser webBrowser = sender as WebBrowser;
//To execute the event just one time
webBrowser.DocumentCompleted -= LoginEvent;
//load page's document
HtmlDocument doc = webBrowser.Document;
doc.GetElementById("u").SetAttribute("value", "admin");
doc.GetElementById("pw").SetAttribute("value", "123456");
foreach (HtmlElement elem in doc.GetElementsByTagName("a"))
{
elem.InvokeMember("click");
}
}
Can anyone help me please to figure why the page isn't showing?
1) Your WebBrowser object is a local variable in your MainWindow() constructor.
This object is being deposed once the MainWindow constructor ends.
You need to declare the WebBrowser object as a class member.
2) There might be a multiple DocumentComplete events being fired. You need to filter out all iFrame events and wait before the page being fully loaded:
private void LoginEvent(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// filter out non main documents
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//To execute the event just one time
webBrowser.DocumentCompleted -= LoginEvent;
//load page's document
HtmlDocument doc = webBrowser.Document;
doc.GetElementById("u").SetAttribute("value", "admin");
doc.GetElementById("pw").SetAttribute("value", "123456");
foreach (HtmlElement elem in doc.GetElementsByTagName("a"))
{
elem.InvokeMember("click");
}
}
I am working for a screen scrapping application from windows application
I can automatically navigate through login page and all the pages using the we browser methods and sometimes having to use the '.Click' to trigger buttons on some of the pages.
Here's the problem. When I do the final 'click' to get my data, web browser opens up a new explorer window(pop up windows) that contains the another link button and I have to do click on this link button using c# to get my final data.
How can I access the new window(pop up window) to scrape it?
I am using below code and this code open the URL in new pop up window.
HtmlElement toollinkbutton = WebBrowser1.Document.Window.Document.Body.Document.GetElementsByTagName("a")[48];
toollinkbutton .InvokeMember("click");
The new window may be due to target="_blank" or javascript and using InvokeMember will result in the new window opening. Add a handler to the WebBrowser control NewWindow event and handle the click by calling Navigate() instead.
private string url = "";
public Form1()
{
InitializeComponent();
WebBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
WebBrowser1.NewWindow += new System.ComponentModel.CancelEventHandler(webBrowser1_NewWindow);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlElementCollection links = WebBrowser1.Document.Links;
foreach (HtmlElement var in links)
{
var.AttachEventHandler("onclick", LinkClicked);
}
}
private void LinkClicked(object sender, EventArgs e)
{
HtmlElement link = WebBrowser1.Document.ActiveElement;
url = link.GetAttribute("href");
}
void webBrowser1_NewWindow(object sender, System.ComponentModel.CancelEventArgs e)
{
WebBrowser webBrowser = (WebBrowser)sender;
HtmlElement link = webBrowser.Document.ActiveElement;
Uri urlNavigated = new Uri(link.GetAttribute("href"));
WebBrowser1.Navigate(url);
e.Cancel = true;
}
I'm trying to parse content from URL's that contains a lot of Javascript generated content, for that I'm using WebBrowser control. Initially I had many issues when loading all the urls of my list of target urls in the same instance of the object, so I decided to dispose the object every few requests and then create a new instance and so on. The issue I'm facing now is that sometimes, when I Dispose the object, it opens a new IE browser window, independent from my application, loading the url's of the object that I've already disposed. Here is my code:
I saw a similar answer in this post, but it's not working for me.
Why is sometimes WebBrowser.Dispose() launching Internet Explorer?
private void TriggerNavigation ()
{
if (urlList.Count > 0)
{
progressBar1.Value++;
if (LoopUrls++ >= 1)
{
URL = string.Empty;
LoopUrls = 0;
timerAjaxLoad.Stop();
webBrowser1.Stop();
webBrowser1.AllowNavigation = false;
webBrowser1.Dispose();
webBrowser1 = null;
GC.Collect();
webBrowser1 = new WebBrowser();
}
URL = urlList.First();
label1.Text = "Processing.." + URL;
webBrowser1.ScriptErrorsSuppressed = true;
webBrowser1.Navigate(URL);
webBrowser1.Navigating += webBrowser1_Navigating;
timerAjaxLoad.Start();
urlList.RemoveAt(0);
}
else
{
timerAjaxLoad.Stop();
}
}
UPDATE:
I figured out what was causing the issue. It was not happening for all the pages, but only for some with embedded JS that was triggering an external page. By catching the Navigating event and cancel the script calls to that page, it solved the issue.
void webBrowser1_Navigating (object sender, WebBrowserNavigatingEventArgs e)
{
foreach (HtmlElement x in ((WebBrowser)sender).Document.GetElementsByTagName("script"))
{
if (x.OuterHtml.Contains("survey"))
e.Cancel = true;
}
foreach (HtmlElement x in ((WebBrowser)sender).Document.GetElementsByTagName("iframe"))
{
e.Cancel = true;
}
}
I figured out what was causing the issue. It was not happening for all the pages, but only for some with embedded JS that was triggering an external page. By catching the Navigating event and cancel the script calls to that page, it solved the issue.
void webBrowser1_Navigating (object sender, WebBrowserNavigatingEventArgs e)
{
foreach (HtmlElement x in ((WebBrowser)sender).Document.GetElementsByTagName("script"))
{
if (x.OuterHtml.Contains("survey"))
e.Cancel = true;
}
foreach (HtmlElement x in ((WebBrowser)sender).Document.GetElementsByTagName("iframe"))
{
e.Cancel = true;
}
}
I want to be able to click on button and than wait for the page to load.
I search, but there is no solution that work correctly.
This is part of code:
el = webBrowser1.Document.GetElementById("LoginButton");
el.InvokeMember("click");
webBrowser1.Navigate(url);
I need it to be that after click, the application will load the page, and only then go to another page.
Also, webBrowser1.Navigate(url) must be in the same method as click. Because it all in a loop.
Please help.
EDITED.
*More code* (first code was and example of what i need)
List<string> list1 = new List<string>();
bool flag = true;
while (flag)
{
flag = false;
foreach (HtmlElement he2 in webBrowser1.Document.GetElementsByTagName("a"))
{
if (he2.GetAttribute("href").Contains("profile.php?ID="))
{
list1.Add(he2.InnerText);
}
}
foreach (HtmlElement he in webBrowser1.Document.GetElementsByTagName("a"))
{
if (he.InnerHtml == "Next")
{
flag = true;
he.InvokeMember("click");
}
}
}
When I click, next page must load, and i have to parse tag on next page, but it begin parse page before next page is load, so it parse the same page.
Finally, I just got href from my button and used this code(insted of he.InvokeMember("click"))
:
webBrowser1.Navigate(url_next);
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
Application.DoEvents();
It works fine.
You can use the DocumentCompleted event to find out when the login has completed.
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
el = webBrowser1.Document.GetElementById("LoginButton");
el.InvokeMember("click");
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Uri myUrl = new Uri("http://stackoverflow.com");
if (e.Url == myUrl)
{
WebBrowser1.Navigate(url);
}
}
I have a webbrowser control in my Winform application.
Below regions belong to division of code sample.
Region 1
The current url page loaded is "http://MyWebsite.com". I am clicking a link (say "About Us") in the web page using code. This click will take me to new url page ("http://MyWebsite.com/About_Us"). In Navigating event I am recording this new url.
Region 2
Now I want to get all elements of this new url and click on a new link. But not sure how to do it. In Region 2 I am also assigning the new url to webbrowser object. But nothing reflects in the instance. webbrowser.url still contains the previous url path.
I have following code for button click:
private void Button1Click(object sender, EventArgs e)
{
// Region 1---------------------------------------------
HtmlElementCollection links = webBrowser1.Document.GetElementsByTagName("A");
foreach (HtmlElement link in links)
{
if (link.InnerText != null && link.InnerText.Equals("Click to view magic"))
{
link.InvokeMember("Click");
break;
}
}
// EndRegion---------------------------------------------
// Region 2---------------------------------------------
webBrowser1.Url = new Uri(_url.AbsoluteUri, UriKind.Absolute);
webBrowser1.Navigate(_url); //New Edit
links = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement link in links)
{
if ((link.GetAttribute("Name") == "BooHoo"))
{
link.InvokeMember("Click");
break;
}
}
// EndRegion---------------------------------------------
}
private void WebBrowser1Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
_url = e.Url;
}
Can anyone help me to do this. The question may not be very clear. Please let me know if you need any further details. Thanks.
So it was tricky a bit or else I am careless. I was watching the property values in debug mode. Later I noticed that, after pressing F5 in Visual Studio (continue debugging) and all the methods are run, webbrowser shows the changed values.
Hope it helps.
You need to subscribe Navigated event as WebBrowser works asynchronously.
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
--Do Something Here....
}