SetAttribute is too slow, following InvokeMember is ignored by the program - c#

I am quite new in visual C# and I'm trying to code an auto login program. Basically all i need is to know SetAttribute and InvokeMember for now.
To simplify the task, I have tried to make a form that will go to google, use SetAttribute to change query box to the user input and use InvokeMember to click "search" button. However code ignores the InvokeMember function when I try to run them in order.
Here is my code:
webBrowser1.Navigate("www.google.com");
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }
webBrowser1.Document.GetElementById("q").SetAttribute("value", searchTXT.Text);
//MessageBox.Show(webBrowser1.Document.GetElementById("q").GetAttribute("value"));
webBrowser1.Document.GetElementById("btnK").InvokeMember("click");
it basically ignores the last line. However when I uncomment the messagebox, it works. It also works when I use a seperate button for clicking, so last line itself should be okay.
I think it is some kind of a delay problem. So I have to wait SetAttribute to finish its job before I call InvokeMember. I tried a while loop to put some delay but it didnt work. Is there any way to wait an operation to complete before proceeding? Is it the actual cause of my problem?
I would really appreciate any help,
Thanks in Advance!

Well eventually "System.Threading.Thread.Sleep(150);" did not work, and I noticed that for some reason
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }
terminates itself before the Web Browser completely loads. In order to make sure that the pages is loaded what I did was to create a bool variable called "wait". Then I changed the code to the following:
wait = true;
webBrowser1.Navigate("www.google.com");
while (wait==true) { Application.DoEvents(); }
webBrowser1.Document.GetElementById("q").SetAttribute("value", searchTXT.Text);
//MessageBox.Show(webBrowser1.Document.GetElementById("q").GetAttribute("value"));
webBrowser1.Document.GetElementById("btnK").InvokeMember("click");
and I double clicked webBrowser1 and set its "completed" event to be wait=false; which worked perfectly fine for me.

Related

How long am I supposed to wait to do something after I call WebBrowser.Refresh?

I have a web page that I am tearing elements out of for use in a program I am writing. It takes a moment for a particular element to load into the web page, so I thought I would use WebBrowser.Refresh() in order to accomplish getting the up to date code.
Unfortunately doing so causes a whole lot of headache if you want to do ANYTHING afterwards since it doesn't fire the DocumentCompleted event (before anyone asks, it even says that explicitly on the MSDN).
So I need a method to allow the program like 2 seconds of doing nothing after it refreshes the page. The problem is that I don't know how to do that and be able to get the updated WebBrowser.Document. If I use Thread.Sleep, the entire application hangs while it sleeps and nothing gets updated.
And if I immediately try, I invariable get the crappy crappy problem of the WebBrowser object hanging forever or throwing Null Cast exceptions.
Has anyone else had this sort of problem (or something similar) and found a solution?
Why don't you just navigate to the URL again?
webBrowser1.Navigate(webBrowser1.Url);
This will fire the event handlers that you need.
I had a similar problem in getting a WebBrowser to refresh at a desired time. As you are discovering, it is hopeless to try to get it to refresh on demand; the HTTP response and HTML rendering are both non-deterministic.
My advice is to attach to the DocumentCompleted event of the WebBrowser, call the desired web page early in the background and show the user something to distract them, then show the completed WebBrowser after DocumentCompleted fires.
If you want to be lazy and not use background threads:
wb.Refresh();
while ((wb.ReadyState != WebBrowserReadyState.Complete)) {
Application.DoEvents();
}
//Refresh is now complete
ReadyState should only be WebBrowserReadyState.Complete once all Ajax and content has completed loading.

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;

Focus() on TextBox does not work

I have a Form with a TextBox in it. Every time the text changes i use the TextChanged Event to create a PDF-file and load it to an AxAcroPDF-Object in the same Form. This works fine, but then the TextBox loses focus and for some reason the textBox.Focus() after loading the file doesn't work.
Has anyone ideas how I can arrange that you can go on typing while refreshing the PDF?
EDIT:
i had another idea, i made a separate thread where i update the PDF and in the TextChanged-event i only set a flag. But now im getting a strange error
Unable to cast COM object of type 'System.__ComObject' to interface type 'AcroPDFLib.IAcroAXDocShim'.
Try this one:
textBox.Select();
textBox.Focus();
Im so ashamed of myself, i found a really, really dirty hack, but it works...
I did the following:
When i write a text in the MessageBox i rewrite my PDF in the TextChange-Event. In the same method i store the Control that has focus (when calling the LoadFile on the PDF-Object this Control still loses focus). And now the dirty work comes: I implemented a Thread that constantly sets focus to the Control stored in the variable. In the Leave-Event of the TextBox i reset the variable so other controls wont be blocked.
Its a really dirty hack i know, but now i can instantly "edit" a pdf with my own form, which is a nice eyecandy ;)
Thanks for all the help!
I could not get .Focus() and .Select() to work so I used Jquery and it works perfectly.
$(document).ready(function () {
setTimeout(function () {
$(".contentWrapper input")[0].focus();
}, 100);
});

Go Back in WebBrowser

I can't find any doucmentation on this. I have a WebBrowser control for my C# Windows Phone app, and I would like to have a button to take the user back one page. How can I do this? (I know how to make the button or access the physical back button, the question is just about how to make a function to take the user back one page.
Thanks.
EDIT: Also, if there's nothing to go back to, I'd like to run another function if possible.
EDIT: Tried this: browser.InvokeScript("eval", "history.go(-1)");, it's not working for some reason. It just closes the app.
EDIT: Got the above working with e.Cancel = true; but how do I restore the default function if there is no page to go back to...?
There are a couple of suggestions in this thread that may work, especially since you don't have to worry about multiple browsers. One way is to use the `history.length' property:
if(history.length > 0)
{
//go back
}
else
{
//cannot go back so perform other function
}
Another way suggested in that thread is to check the referrer. The first page doesn't usually have a referrer:
if (document.referrer == "") {
window.close()
} else {
history.back()
}
Invoke these scripts the same way you invoked the history.go() script and see if that works.

Problem with Application.DoEvents() while waiting for WebBrowser to finish loading

I'm trying to load WebBrowser content and after that I want to add some text and scroll to the bottom.
Here's example of my code:
webBrowser1.Url = new System.Uri("file:///" + filePath);
webBrowser1.Document.Body.InnerHtml += text;
webBrowser1.Document.Body.ScrollTop = webBrowser1.Document.Body.ScrollRectangle.Height;
When I run it, there's an unhandled exception "Object reference not set to an instance of an object". Or when I comment line that does the scrolling, then text is added to previous content of the WebBrowser and then navigating to new content.
So after 1st line of my example code I put:
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
but it messes up everything. My application is doing really strange things, for example calling the same method many times, when it should be called once.
Is there any solution?
I think you actually want to subscribe to DocumentCompleted event.
Application.DoEvents only processes pending Windows message loop items.
In either case, make sure you understand possible drawbacks of calling DoEvents before using it at all.
DoEvents() is a bad solution here. You should use explicit thread or BackgroundWorker to load pages and leave UI thread to handle other stuff.

Categories

Resources