WebBrowserDocumentCompletedEventHandler is repeating itself - c#

I am trying to make a program that harvester data from a remote login site. I manage to log my self in but when i try to navigate through 2 pages my code makes the browser request and loads p1 then p2 then p1 then p2 and so on.
I try all methods within this link How to make WebBrowser wait till it loads fully?
And it stills gives me the same problem!
Here is my code:
webBrowser1.Document.GetElementById("user").InnerText = textBox1.Text.ToString();
webBrowser1.Document.GetElementById("pass").InnerText = textBox2.Text.ToString();
webBrowser1.Document.GetElementById("login").InvokeMember("click");
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(LookNew);
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(Lookfind);
void LookNew(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url != webBrowser1.Url)
return;
else
FindLink(webBrowser1.DocumentText, "New").InvokeMember("Click");
}
void LookFind(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url != webBrowser1.Url)
return;
else
FindLink(webBrowser1.DocumentText, "find").InvokeMember("Click");
}

Related

C# Wait for Web Page to Load Before Scraping

I am trying to make a Windows Forms app that logs in another web application, navigates for a few steps (clicks) until it reaches a specific page and then scrape some info (names and addresses).
The problem is that I am using the DocumentCompletedEventHandler in order to have a page loaded before I execute the code for navigating to the next page (in order to reach the final web page).
When it fires, DocumentCompletedEventHandler fires multiple times.
When I reach the loggin page, it enters the credentials and then the message "Page loaded!" appears multiple times.
I press enter, it appears again.
Then it navigates to the next page and with that new page I have the same problem.
how can I make DocumentCompletedEventHandler to fire only once and not multiple times?
private void loadEvent(object sender, WebBrowserDocumentCompletedEventArgs e)
{
MessageBox.Show("Page loaded!");
}
private void loadLogin(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var inputElements = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement i in inputElements)
{
if (i.GetAttribute("name").Equals("utilizator"))
{
i.InnerText = textBox1.Text;
}
if (i.GetAttribute("name").Equals("parola"))
{
i.Focus();
i.InnerText = textBox2.Text;
}
}
var buttonElements = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement b in buttonElements)
{
if (b.GetAttribute("name").Equals("Intra"))
{
b.InvokeMember("Click");
}
}
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(loadEvent);
var inputElements1 = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement i1 in inputElements1)
{
if (i1.GetAttribute("id").Equals("headerqstext"))
{
i1.Focus();
i1.InnerText = textBox3.Text;
}
}
var buttonElements1 = webBrowser1.Document.GetElementsByTagName("button");
foreach (HtmlElement b1 in buttonElements1)
{
if (b1.GetAttribute("title").Equals("Caută"))
{
b1.InvokeMember("Click");
}
}
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(loadEvent);
}
private void Button1_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("http://10.1.104.23/ecris_cdms/");
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(loadLogin);
}
}
}
try this :)
Uri last = null;
private void CompleteResponse(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (!(last != null && last != e.Url))
return;
//your code here
}

ShowDialogue not generating DialogueResult.OK

I'm writing a program that's supposed to download something off GitHub. It has a link to a raw file on GitHub. I'm using DownloadDataAsync to download it, and I have a progress bar to track how far it is in the download. It always gets to 100%, but then it does nothing.
I've been following a tutorial for a C# updater by BetterCoder (The beginning starts here and the most relevant part would be Part 9 of the series).
This is the part where it stops working properly:
private void DownloadUpdate(SaveyourUpdateXML update)
{
SharpUpdateDownloadForm form = new SharpUpdateDownloadForm(update.Uri, update.MD5, this.applicationInfo.ApplicationIcon);
Debug.WriteLine("form created");
DialogResult result = form.ShowDialog(this.applicationInfo.Context);
Debug.WriteLine("got result");
if (result == DialogResult.OK)
{
String currentPath = this.applicationInfo.ApplicationAssembly.Location;
String newPath = Path.GetDirectoryName(currentPath) + "\\" + update.FileName;
UpdateApplication(form.TempFilePath, currentPath, newPath, update.LaunchArgs);
Application.Exit();
}
}
It never gets to the "got result" part unless I cancel it. Also, this.applicationInfo.Context returns a form. However, it does say "form created".
I think there's something wrong with the way ShowDialog is used or something, but I'm not really sure what.
Edit: This is what happens when a SharpUpdateDownloadForm is created.
internal SharpUpdateDownloadForm(Uri location, String md5, Icon programIcon)
{
InitializeComponent();
if (programIcon != null)
{
this.Icon = programIcon;
}
tempFile = Path.GetTempFileName();
this.md5 = md5;
webClient = new WebClient();
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
bgWorker = new BackgroundWorker();
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
try
{
webClient.DownloadDataAsync(location, this.tempFile);
}
catch
{
this.DialogResult = DialogResult.No;
this.Close();
}
}
This is what should happen when a download is completed:
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
this.DialogResult = DialogResult.No;
this.Close();
}
else if (e.Cancelled)
{
this.DialogResult = DialogResult.Abort;
this.Close();
}
else
{
lblProgress.Text = "Verifying Download...";
progressBar.Style = ProgressBarStyle.Marquee;
bgWorker.RunWorkerAsync(new string[] {this.tempFile, this.md5});
}
}
This is bgWorker_RunWorkerCompleted
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.DialogResult = (DialogResult)e.Result;
this.Close();
}
And bgWorker_DoWork
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
String file = ((string[])e.Argument)[0];
String updateMD5 = ((string[])e.Argument)[1];
if (Hasher.HashFile(file, HashType.MD5) != updateMD5)
e.Result = DialogResult.No;
else
e.Result = DialogResult.OK;
}
When webClient.DownloadDataAsync completes, it fires DownloadDataCompleted event, not DownloadFileCompleted - the one you registered.
The fix is, if you use webClient.DownloadDataAsync, register the DownloadDataCompleted event; Note that the 2nd argument to webClient_DownloadDataCompleted is different.
webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webClient_DownloadDataCompleted);
...
private void webClient_DownloadDataCompleted(Object sender, DownloadDataCompletedEventArgs e)
{
...
}

Trying to log in to a website through a C# program

I'm new to C# so I looked for this topic in other questions but they weren't for me. What I am trying to do is I currently try to login to my school's servers using a c# program(Which I'm trying to implement). What I'm trying to do is I know the code of the page, so I am using web browser of c# to navigate then I just want to write name and password to the input boxes and this is where I stuck. Can you please give me any advices?
If you want to look at page: https://suis.sabanciuniv.edu/prod/twbkwbis.P_SabanciLogin
Thanks for your advices.
Here how I used the code(Edit: Added eventhandler but this is my first time using so it promts me "object reference not set to a instance of an object"):
private void buttonGo_Click(object sender, EventArgs e)
{
try
{
string input = "https://suis.sabanciuniv.edu/prod/twbkwbis.P_SabanciLogin";
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
webBrowser1.Navigate(input);
HtmlDocument doc = webBrowser1.Document;
HtmlElement userName = doc.GetElementById("UserID");
HtmlElement pass = doc.GetElementById("PIN");
HtmlElement submit = doc.GetElementById("Login");
userName.SetAttribute("value", textID.Text);
pass.SetAttribute("value", textPASS.Text);
submit.InvokeMember("Click");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = sender as WebBrowser;
webBrowser.DocumentCompleted -= WebBrowser_DocumentCompleted;
MessageBox.Show(webBrowser.Url.ToString());
}
}
}
Finally I solved problem I cheated a little but managed to solve. Here is the working code:
private void buttonGo_Click(object sender, EventArgs e)
{
try
{
string input = "https://suis.sabanciuniv.edu/prod/twbkwbis.P_SabanciLogin";
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
webBrowser1.Navigate(input);
HtmlDocument doc = webBrowser1.Document;
//HtmlElement userName = doc.GetElementById("UserID"); These not worked because ID of the elements were hidden so they are here to show which of these did not work.
//HtmlElement pass = doc.GetElementById("password");
HtmlElement submit = webBrowser1.Document.Forms[0].Document.All["PIN"].Parent.Parent.Parent.NextSibling.FirstChild;
//userName.SetAttribute("value", textID.Text);
//pass.SetAttribute("value", textPASS.Text);
webBrowser1.Document.Forms[0].All["UserID"].SetAttribute("value", textID.Text);
webBrowser1.Document.Forms[0].All["PIN"].FirstChild.SetAttribute("value", textPASS.Text);
submit.InvokeMember("Click");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = sender as WebBrowser;
webBrowser.DocumentCompleted -= WebBrowser_DocumentCompleted;
MessageBox.Show(webBrowser.Url.ToString());
}
You need to find the input boxes of the username and password fields as ID's or nodes first. Then assign them as such:
HtmlDocument doc = webBrowser1.Document;
HtmlElement email = doc.GetElementById("email");
HtmlElement pass = doc.GetElementById("pass");
HtmlElement submit = doc.GetElementById("LoginButton");
email.SetAttribute("value", "InsertYourEmailHere");
//Same for password
submit.InvokeMember("Click");

C# stopping an infinite foreach loop

This foreach loop checks a webpage and sees if there are any images then downloads them. How do i stop it? When i press the button it continues the loop forever.
private void button1_Click(object sender, EventArgs e)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted +=browser_DocumentCompleted;
browser.Navigate(textBox1.Text);
}
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
HtmlElementCollection imgCollection = browser.Document.GetElementsByTagName("img");
WebClient webClient = new WebClient();
int count = 0; //if available
int maximumCount = imgCollection.Count;
try
{
foreach (HtmlElement img in imgCollection)
{
string url = img.GetAttribute("src");
webClient.DownloadFile(url, url.Substring(url.LastIndexOf('/')));
count++;
if(count >= maximumCount)
break;
}
}
catch { MessageBox.Show("errr"); }
}
use the break; keyword to break out of a loop
You do not have an infinite loop, you have an exception that is being thrown based on how you are writing the file to disk
private void button1_Click(object sender, EventArgs e)
{
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += browser_DocumentCompleted;
browser.Navigate("www.google.ca");
}
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
HtmlElementCollection imgCollection = browser.Document.GetElementsByTagName("img");
WebClient webClient = new WebClient();
foreach (HtmlElement img in imgCollection)
{
string url = img.GetAttribute("src");
string name = System.IO.Path.GetFileName(url);
string path = System.IO.Path.Combine(Environment.CurrentDirectory, name);
webClient.DownloadFile(url, path);
}
}
That code works fine on my environment. The issue you seemed to be having was when you were setting the DownloadFile filepath, you were setting it to a value like `\myimage.png', and the webclient could not find the path so it threw and exception.
The above code drops it into the current directory with the extension name.
Maybe the Event browser.DocumentCompleted cause the error, if the page refreshes the event gets fired again. You could try to deregister the event.
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
browser.DocumentCompleted -= browser_DocumentCompleted;
HtmlElementCollection imgCollection = browser.Document.GetElementsByTagName("img");
WebClient webClient = new WebClient();
foreach (HtmlElement img in imgCollection)
{
string url = img.GetAttribute("src");
string name = System.IO.Path.GetFileName(url);
string path = System.IO.Path.Combine(Environment.CurrentDirectory, name);
webClient.DownloadFile(url, path);
}
}

C# How to do WebBrowserDocumentComplete in a foreach loop

I thought this might be simple but i guess it's not, i have like 100 websites i need to load into a browser. I've loaded them into a List but my foreach happens before the website loads. Does anybody have a way to make each of these load and actually process WebBrowserDocumentComplete before loading the next one? queue doesn't work.
foreach(string oneWebsite in ALLWebSites)
{
webBrowser1.Navigate(oneWebsite);
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//do work
}
An AutoResetEvent should work
http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitone(v=vs.71).aspx
static AutoResetEvent autoEvent = new AutoResetEvent(false);
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
foreach(string oneWebsite in ALLWebSites)
{
webBrowser1.Navigate(oneWebsite);
autoEvent.WaitOne(new TimeSpan(0, 1, 0), false))
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//do work
autoEvent.Set();
}
At the end of the DocumentCOmplete handler have the browser navigate to the next site in the list.
Something like this should work:
var websiteIndex = 0;
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
private void ProcessWebsite()
{
if (websiteIndex < ALLWebSites.Count)
{
webBrowser1.Navigate(ALLWebSites[websiteIndex]);
websiteIndex++;
}
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//do work
// when work is done, process next one
ProcessWebsite();
}

Categories

Resources