How to do multiple actions in WebBrowser_DocumentCompleted in c# - c#

So, I'm creating a bot using webBrowser in c# that loads a website entered in the text box. When the website is loaded, I need bot to click on a specific anchor text. After that when a new page is loaded, I need to click on another anchor text and so on, until a form to fill out details appears. I also need to show captcha to the user where he/she can fill it and submit it, so that the page can continue to next page.
What I need is to invoke different methods, each time the browser navigated to next page and loading is complete. I have successfully created a WebBrowser_DocumentCompleted, but it get invoked over and over again, due to the fact that same hyper link is present on the page that I want to visit. But, on that page I need to click on a button.
I did this for getting the link and visiting it.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Select the html element by inner text of anchor and click on it
HtmlElementCollection elc = this.webBrowser1.Document.GetElementsByTagName("a");
foreach (HtmlElement el in elc)
{
if (el.InnerText == null || el.InnerText.Equals("Matching text"))
{
el.InvokeMember("click");
}
}
}
After this the link that have matched innretext get clicked and the page loads. The page have same anchor text and it gets loaded again and again. But, I need to click on another button and go to next page.
So, if you have any way that I can use to do it then it would be awesome.Any help is welcomed!
P.S. I'm a beginner in C# and .net

The behaviour you see is normal, I suppose the page you are loading has some iframes or embedded content and for each one loaded the DocumentCompleted will be fired (it's not related on having a link to the page, a link does nothing until it's clicked).
You must take actions based on the Url parameter of the WebBrowserDocumentCompletedEventArgs passed on thos function, in this way you can execute the required action for each concrete page, something like this:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
switch(e.Url.ToString())
{
case "http://myfakeserver.com/mypageone.htm":
//Do whetever you want to do
break;
case "http://myfakeserver.com/mypagetwo.htm":
//Do more stuff
break;
}
}
Hope it helps.
EDIT:
Ok, now I get what you need.
It's easy, just check if you area already on that page.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Select the html element by inner text of anchor and click on it
HtmlElementCollection elc = this.webBrowser1.Document.GetElementsByTagName("a");
foreach (HtmlElement el in elc)
{
var hRef = el.GetAttribute("href");
if(string.IsNullOrWhitespace(hRef))
continue;
var lnkUri = new Uri(hRef);
//If the link points to this page, ignore it
if(lnkUri.Segments[lnkUri.Segments.Length - 1] == e.Url.Segments[e.Url.Segments.Length - 1])
continue;
if ((el.InnerText == null || el.InnerText.Equals("Matching text"))
{
el.InvokeMember("click");
}
}
}
Beware in the example i'm just checking the last part of the url, so if you have different paths which have the same page name it will fail, you must adapt it to your needs, depending on how the uris are written on the href you can do a full check of the urls.

Related

Can you "remember" what link is clicked on a webpage?

I'm working in Visual Studios to create a website for a movie theater (for class) I'm wondering if there's a way to "remember" what link is clicked for a show time? I know I could just create a webpage for each time, but I'd rather track an id, if that's possible!
By clicking the link, they'll go to the right page, but is there any way for me to put into the system what time they clicked? I couldn't find any similar questions here.
you could use sessions to hold the showtime selected. create an LinkButton with an onCommand that creates a session before redirecting them to the seating chart or checkout page.
so say a user is on your movie page and the user selects the 12pm showtime. When the user clicks on the link, it will run what ever is in your code behind. You can create a Session["DateTime"] and set it to the value of the linkbutton. then, redirect to the seating page.
on the seating page, you can check if there's a session. if it finds one, then you can load the seating chart or purchasing page. if it does not find one, you might want to redirect them back to select a time.
HTML example:
<h2>Next Big Movie</h2>
<asp:LinkButton id="lbNBM12pm" runat="server" OnCommand="lb_Click" text="12:00pm"></asp:LinkButton>
Code Behind example:
protected void lb_Click(object sender, EventArgs e)
{
string time = (sender as LinkButton).Text;
Session["TimeSelected"] = time;
Response.Redirect("/nextstep.aspx");
}
and on the next page, you'll read what was passed over in the page load and set the Selected Movie time text:
protected void Page_Load(object sender, EventArgs e)
{
if(Session["TimeSelected"] != null)
{
MovieTime.Text = Session["TimeSelected"].ToString();
}
else
{
//user did not select a time
//possibly redirect them back to the showtimes page.
response.redirect("/previousepage.aspx");
}
}
If I understand it correctly. First, create a table with the following columns:
create table Links
(
id int identity,
link varchar(100),
timeclicked datetime
)
then fire an ajax or a simple HTML POST request to submit what link is clicked in a spefic time.

how to display full Url in web browser control properly in C#?

I can display the Url in the searchbar. However, it picks up javascript and other loading processes as URL and displays them and doesn't display a conventional Url (e.g https://stackoverflow.com/questions) that we would see in any common browser. So if I search http://www.stackoverflow.com, I get https://ssum-sec.casalemedia.com/usermatch?s=183712&cb=https://engine.adzerk.net/udb/22/sync/i.gif?partnerId=1&userId=. Any help would be appreciated.
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
player.SoundLocation = "safepage.wav";
player.Play();
if (SearchBar.Text != e.Url.ToString()) //Displays the full Webpage address within the textbox
{
SearchBar.Text = e.Url.ToString();
}
}
Navigation events of web browser control will raise for iframes of the page too. So in this case, what you are getting as result is address of an iframe in the page.
You can use webBrowser1.Url.ToString() instead of e.Url.ToString().
Note: As far as I know, there should not be an iframe in stackoverflow questions page, so itt seems your browser has been infected.
In the _Navigated event, you can use the WebBrowser.Url property. It will get updated each time but not for the redirects like for those tracking/ad scripts.

Program to automate form field entry and result checking of webpage

I am trying to create a program in C# (maybe using WinForms) which will enter a licence number into a form field of a specific website and validate whether or not the licence number is a currently valid licence.
I am unsure as to where to start, as I can't even find the form field id in the source code of the website, and am unsure what technologies the website uses.
Additionally, the purpose of this program will be to enter a list of license numbers and return the names and validation status of each license. Datasource being the website.
Any information on how to go about this would be much appreciated, I am an intermediate C# developer - having mostly worked in ASP.Net, though feel Winforms may be better suited for this project.
Kind Regards
You can use a WebBrowser control:
You can load the page using webBrowser1.Navigate("url of site")
Find elements in page using webBrowser1.Document.GetElementById("buttonid") also you can iterate over HtmlElement of webBrowser1.Document.Body.All and check for example element.GetAttribute("value") == "some vaule" to find it.
Set value for element using element.InnerText ="some value" or element.SetAttribute("value", "some value")
Submit your form by invoking the submit of form or click of its submit button using element.InvokeMember("method")
Example
For example, if you browse google and look at page source, you will see name of search text box is "q" and name of the form that contains the search box is "f", so you can write this codes to automate search.
Create a form with name BrowserSample.
From toolbox, drag a WebBrowser and drop on form.
Hanfdle Load event of form and navigate to google.
Handle DocumentCompleted event of webBrowser1 and find f and find q and set InnerText of q and invoke submit of f. This event fires after the navigation and document load completed.
In a real application add required null checking.
Code:
private void BrowserSample_Load(object sender, EventArgs e)
{
this.webBrowser1.Navigate("https://www.google.com/");
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Because submitting f causes navigation
//to pervent a loop, we check the url of navigation
//and if it's different from google url, return
if (e.Url.AbsoluteUri != "https://www.google.com/")
return;
var f = this.webBrowser1.Document.Body.All.GetElementsByName("f")
.Cast<HtmlElement>()
.FirstOrDefault();
var q = f.All.GetElementsByName("q")
.Cast<HtmlElement>()
.FirstOrDefault();
q.InnerText = "C# Webbrowser Control";
f.InvokeMember("submit");
}
If you execute the program, it first navigate to google and then shows search result:
In your special case
Since the site loads content using ajax, then you should make a delay in DocumentCompleted:
async void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsoluteUri != "https://www.onegov.nsw.gov.au/PublicRegister/#/publicregister/search/Security")
return;
await Task.Delay(5000);
var f = this.webBrowser1.Document.Body.All.GetElementsByName("searchForm")
.Cast<HtmlElement>()
.FirstOrDefault();
var q = f.All.GetElementsByName("searchText")
.Cast<HtmlElement>()
.FirstOrDefault();
q.InnerText = "123456789";
f.InvokeMember("submit");
}
Don't forget to add using System.Threading.Tasks; or if you use .Net 4.0 you simple can use System.Threading.Thread.Sleep(5000) and remove async/await.
It looks like the website uses JSON POSTs. If you have FireFox open Developer -> Network and look at the "PerformSearch" entry. That will tell you everything you need to know as far as what the website is expecting in a POST request so you can read the response.

web browser delete element's outer html

I have a C# application which has a web browser, navigating to a specified page by default.
What I want to do is when the document has completely loaded, select a html element by tag name(not ID/Class) and then delete the html outside of it but I have tried for some time and still didn't success..
This is my event and where I got so far
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var elementToDelete = webBrowser1.Document.GetElementsByTagName("form");
}
I want to select that form element which has no CLASS/ID and delete all html code that is outside of it(outer-html) so it will be the only thing visible on the page.
You say that you want to delete an element, but then after your code you say that you want to delete everything outside of "form". I'm not sure which you actually want, but you can do the second with the following.
First, note that elementToDelete is actually a collection, not a single element, so we need to get a single element.
var formElements = webBrowser1.Document.GetElementsByTagName("form");
var elementToSave = formElements.FirstOrDefault();
if(elementToSave == null)
throw new InvalidOperationException("No element named 'form'");
You can then set the Document.DocumentText property to the InnerHtml property of "form". You should probably wrap up the inner HTML so that it's a valid page, but this should work:
webBrowser1.Document.DocumentText = elementToSave.InnerHtml;

ASP.NET: How to handle all page redirection?

In an ASP.NET page, are there any practical ways to handle all of these following:
PostBack
Redirection when user click a link in the page
Redirection when user change url field in the browser
with just a single web control (or method)?
TQ
Postback can be handled on the Server Side
the two others - link click or url field are ought to be handled using Javascript only.
UPDATE:
You can use jQuery to show a "loading animation" as mentioned in the question
$(window).unload( function () { alert("Bye now!"); } );
This will issue an alert once the user tries to leave the page. you can change it so it will display an animating gif image.
This must be tested though. I think it's pointless; not too sure on how long the gif will be displayed until the browser starts to load up the new page.
EDIT:
As I mentioned in comments, you can issue a postback using javascript
so, according to my last edit
$(window).unload( function () { __doPostBack("leaving"); } );
will issue a postback to the server, and you can catch it by:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.PreLoad += (sender, args) =>
{
this.ClientScript.GetPostBackEventReference(this, "arg");
if (!IsPostBack) { return; }
string __targetaction = this.Request["__EVENTTARGET"];
string __args = this.Request["__EVENTARGUMENT"];
if (string.IsNullOrEmpty(__args)) return;
if (__targetaction == "leaving")
{
doSomething();
}
};
}
then again, I'm not too sure this will be too helpful, since the user is leaving the page.
PostBack
In this Page.IsPostBack will be = true
Redirection when user click a link in the page
In this case you will get value in referrer. You can use Request.ServerVariables["http_referer"] OR Request.UrlReferrer
Redirection when user change url field in the browser
Else this is the 3rd case

Categories

Resources