Use asynchrony with GeckoFX web browser - c#

I have a problem, I am trying to work with a custom webbrowser for a specific website.
The problem I am having with GeckoFX is that some times I need to wait for DocumentCompleted to continue with execution of particular methods.
I don't want to put all my code into one large DocumentCompleted event, as that seems silly and wrong.
I got the code to work by using the Application.DoEvents() as follows, but I read that this is not a right way to go, and that webbrowser should be best run as async.
private void AddNewTab(string tmsAddress) //add a new browser to my form
{
TabPage tab = new TabPage();
browserTabControl.TabPages.Insert(browserTabControl.TabCount - 1, tab);
GeckoWebBrowser browser = new GeckoWebBrowser();
tab.Controls.Add(browser);
tmsBrowser.Dock = DockStyle.Fill;
tmsBrowser.Navigate(address);
tmsBrowser.DocumentCompleted += new EventHandler<Gecko.Events.GeckoDocumentCompletedEventArgs>(tmsBrowser_DocumentCompleted);
}
Navigation on the page is manual, i.e. users work with the page normally, but from time to time they can use a shortcut button to get somewhere.
private void someButton_MouseUp(object sender, MouseEventArgs e)
{
GeckoWebBrowser browser = getCurrentBrowser();
//get some data from the page here
OpenPageInContentFrame(address + parameter1 + parameter2); //I need to wait for this page to load and then do HighlightItemRow()
while (!eventHandled) //documentCompleted events sets the bool as 'true'
{
Application.DoEvents();
}
HighlightItemRow(browser, parameter1);
}
}
I wanted to go with ManualResetEvents instead of while() and Application.DoEvents(), but using manResEvent.WaitOne() causes the whole application to freeze, including the navigation, so the page never actually loads. I think this must be because it's all in a single thread, I don't know how to make it working - I never used anything async etc.

Related

C# - Wait for a WebBrowser to completely finish navigating and loading a website/webpage

I'm trying to do web automation by creating a Windows Form application in C# using WebBrowser. I currently have the code below that navigates to Youtube and inputs a string in Youtube's search bar.
website.Navigate("www.youtube.com");
website.Document.GetElementById("search").InnerText = "Cavaliers vs Boston highlights";
However, I get a NullReferenceException in the line
website.Document.GetElementById("search").InnerText = "Cavaliers vs Boston highlights";
I tried searching in different websites on how a WebBrowser is able to determine if it has completely finished loading the website you have specified in the Navigate method but so far I haven't found any.
What I have found online are methods that checks a WebBrowser's ready state but upon trying it, it doesn't even load the Form I created, yet still proceeds to the GetElementById method.
Hoping someone can help me with this, been trying to find a solution since morning.
Try to add an event listener to WebBrowser. The WebBrowser has a WebBrowser.DocumentCompleted event that occurs when the web page has been fully loaded.
Something like
public frmMain()
{
website.DocumentCompleted += website_DocumentCompleted;
}
public void website_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
website.Document.GetElementById("search").InnerText = "Cavaliers vs Boston highlights"
}
where frmMain is your form. It could be of course added in somewhere else too.

C# How to unsubscribe click for BaloonToolTip

I'm writing an application that shows notifications trough baloontips over notifyicon. There are two kinds of notifications I want to display - normal baloontip and clickable baloontip. I want clickable baloontips to open some url in web browser. The problem is that events stacks over baloontip.
I'm not sure if this explanation says anything, so here's an example:
code:
NotifyIcon ni = new NotifyIcon();
void showClickableNotification(string title, string content, string url)
{
ni.BaloonTipClicked += new EventHandler((sender, e) => ni_BalloonTipClicked(sender, e, url));
ni.ShowBaloonTip(1, title, content, ToolTipIcon.Info);
}
void ni_BalooTipClicked(object sender, EventArgs e, string url)
{
Process.Start(url);
}
every use of showClickableNotification will assign one more url to BallonTipClicked event
I want to clear event after notification will hide, to prevent opening multiple tabs unassociated with current notification.
Also, when normal notification is shown after a clickable one it's click opens all the stacked urls as well.
I tried to assign an empty function for ni.BaloonTipClicked += emptyFunction this, but += operator just adds another event to the pool instead of overwriting it. -= does not work since I'm adding new event every time. I guess I could do some global variable that holds current url and avoid assigning new everytime (-= would work then), but it looks like cheap workaround. Is there any (correct?) way to do it?

Prevent Page Caching and Back Button

I am trying to prevent the back button being used by expiring the pages.
I have been trying to find an article on here to help and nothing works.
I have the function below that I call as the first thing on all my pages.
I call it in the Page_Load handler, is that the right place ?
I see no errors which is good, but my application just reacts as if there is no change. The back/forward buttons work and the pages display as normal and don't expire.
UPDATE:
As an added layer of security, what I want is the page to time out so if they use the "back" button they won't get the previous page. I have F5 covered so that doesn't repeat posts, and login is covered, if as I abandon the Session when they log out. But I want to stop the back button showing the previous page and force them to use the app navigation to get around my application.
I've known this functionality to fail penetration testing so I want to cover that off before I get to that point.
J
protected void Page_Load(object sender, EventArgs e)
{
MyWebApplication.SetPageStatus(Response);
....
}
internal static void SetPageStatus(System.Web.HttpResponse oResponse)
{
oResponse.ClearHeaders();
oResponse.ExpiresAbsolute = DateTime.Now;
oResponse.Expires = 0;
oResponse.CacheControl = "no-cache";
oResponse.Buffer = true;
oResponse.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
oResponse.Cache.SetExpires(DateTime.UtcNow);
oResponse.Cache.SetNoStore();
oResponse.Cache.SetRevalidation(System.Web.HttpCacheRevalidation.AllCaches);
}

Stop Action on Navigating event of WebBrowser Control

I have created a little Win Form App in C# and added the WebBrowser component to it. What i am trying to achieve is a little app that can load a local html page from a file which has "custom" protocols in it and can of course also navigate to a web address.
For example i would have entry as follows in my webpage
'Close Company</TD></TR>' which would open a task in a program.
The way i tried to achieve this was via the Navigating event as shown below
private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
if ((webBrowser.StatusText.Contains("Special")))
{
//For some reason the stop doesn't do much it still tries to proceed to special:123
//diplaying can not load page..
webBrowser.Stop();
//Launch program here.
MessageBox.Show("Special Command Found");
}
}
Problem is that it still navigates and says it can't find of course the page.
I swapped Stop with GoBack which for some reason has the same issue the first time i run it and when i then select backward in the browser it works from thereon.
I also tried navigated and use of GoBack, besides having a flashing in the app from going back the event does not fire again after the first time anymore.
Has anyone any ideas how to solve this or what i am doing wrong here ?
Instead of using WebBrowser.Stop();
just set e.cancel = true;

C# Webbrowser Control: Navigating to a List to URLs

I am working on a web crawler. I am using the Webbrowser control for this purpose. I have got the list of urls stored in database and I want to traverse all those URLs one by one and parse the HTML.
I used the following logic
foreach (string href in hrefs)
{
webBrowser1.Url = new Uri(href);
webBrowser1.Navigate(href);
}
I want to do some work in the "webBrowser1_DocumentCompleted" event once the page is loaded completely. But the "webBrowser1_DocumentCompleted" does not get the control as I am using the loop here. It only get the control when the last url in "hrefs" is navigated and the control exits the loop.
Whats the best way to handle such problem?
Store the list somewhere in your state, as well as the index of where you've got to. Then in the DocumentCompleted event, parse the HTML and then navigate to the next page.
(Personally I wouldn't use the WebBrowser control for web crawling... I know it means it'll handle the JavaScript for you, but it'll be a lot harder to parallelize nicely than using multiple WebRequest or WebClient objects.)
First of all, you are setting new url to same web browser control, even before it has loaded anything, this way you will simply see the last url on your browser. Definately browser will certainly take some time to load url, so I guess navigation is cancelled well in advance before Document_Completed can be fired.
There is only one way to do this simultaneously,
You have to use a tab control, and open a new tab item for every url and each tab item will have its own web browser control and you can set its url.
foreach(string href in hrefs){
TabItem item = new TabItem();
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += wb_DocumentCompleted;
wb.Url = href;
item.Child = web;
tabControl1.Items.Add(item);
}
private void wb_DocumentCompleted(object sender, EventArgs e){
/// do your stuff...
}
In order to improve above method, you should see how can you create multiple tab items in different UI threads, its pretty log topic to discuss here, but it is still possible.
Another method is to do use a queue...
private static Queue<string> queue = new ...
foreach(string href in hrefs){
queue.Enqueue(href);
}
private void webBrowser1_DocumentCompleted(object sender, EventArgs e){
if(queue.Count>0){
webBrowser1.Url = queue.Dequeue();
}
}

Categories

Resources