C# - GeckoFX vs InnerHTML - c#

If I would use default Visualstudio webBrowser control (IE) i would just write something like this:
textBox3.Text = webBrowser1.Document.GetElementById("mydivid").InnerHtml;
But I'm stubborn to use GeckoFX (Mozilla) and ofcourse it doesn't work. What I found is information that I need to adress "HTMLDocument" not "Document" to pull my desired value. But no example that fit my needs.
How to get this innerHTML of this particular element?
--- Response to #Timothy Groote ---
I've read the other topic - there's no example of code with GetElementById, it's like wide definition, but I need specific one - I cannot read this codeand get clear information what method or property shoueld I use in my app.
I can add that my element is and will be always HTML element, so i don't need to verify that every time with "if".
When I use "the other code" in my app result (instead of innerHTML) was only:
<head></head><body></body>
In "the other code" has also a mistake:
var geckoDomElement = WebBrowser1.Document.DocumentElement;
There's no webBrowser1 control! Only geckoWebBrowser1, neither works!
--- Edit2 ---
I was also thinking about something like that:
textBox3.text = (GeckoHtmlElement)geckoWebBrowser1.Document.GetElementById("mydivid")....
but there's also no "innerHtml"
in
(GeckoHtmlElement)geckoWebBrowser1.Document.DocumentElement
there's no "getElementById".

If you using Geckofx 45 then its very simple , just try like this....
GeckoHtmlElement testelement = null;
testelement = (GeckoHtmlElement)webBrowser1.Document.GetElementById("test");
string text=testelement .InnerHtml;
if you don't know how to use Geckofx 45 then try this simple tutorial ..
How to use or embed Geckofx 45 Webbrowser control into Visual Studio into WinForms Applications

ANSWER
Of course defining variable:
GeckoHtmlElement machcode;
Finding element:
machcode = geckoWebBrowser1.Document.GetHtmlElementById("machinecode");
And finally reading the content:
textBox3.Text = machcode.InnerHtml;
And one important thing was to place code in DocumentComplete event!
Every solutions provided in web were wrong - some point into nonexisting webBrowser1 control, some forget about definition, some throw null exception, some use wrong GetElement instead of GetHtmlElement.

Related

Why is the Url value in C# WebBrowser always null?

I am trying to load a local HTML file into an instance of C# WebBrowser (WinForms).
This is what I am doing:
string url = #"file:///C:MyHtml/hello.html";
myWebbrowser.Url = new Uri(url, UriKind.Absolute);
object test = myWebbrowser.Url; // breakpoint here
The path above is correct; if I copy it and paste into an external browser, the file is immediately opened. But the instance of WebBrowser does not want to react. I set a breakpoint in the last line of the snippet, and what I get there is that myWebbrowser.Url is null (the test variable). The control remains correspondingly empty.
myWebbrowser.AllowNavigation is explicitly set to true. I have also tried all possible versions of slashes and backslashes; the result is always the same. The version of the webbrowser seems to be 11 (myWebbrowser.Version = "{11.0.18362.1139}"). I am working in Windows 10, VS 2019.
What can be wrong in this setup?
The path above is correct; if I copy it and paste into an external browser, the file is immediately opened. But the instance of WebBrowser does not want to react. I set a breakpoint in the last line of the snippet, and what I get there is that myWebbrowser.Url is null.
I was able to replicate this exact issue, it's because the property of the Url doesn't get actually set until the document has actually finished loading.
To resolve this issue, you must handle the DocumentCompleted event. You can do so for example:
string url = #"file:///C:MyHtml/hello.html";
myWebbrowser.DocumentCompleted += MyWebbrowser_DocumentCompleted;
myWebbrowser.Url = new Uri(url, UriKind.Absolute);
Create a new routine to handle the DocumentCompleted event:
private void MyWebbrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string test = myWebbrowser.Url.ToString();
}
You can also get the Url from the WebBrowserDocumentCompletedEventArgs:
string testUrl = e.Url.ToString();
I am not sure exactly why when setting the Url and then checking it, it is null, I haven't found anything to explain why. My only guess is that it may be an invalid Url and or path, if navigation succeeds then that property is set.
Edit: upon looking at the source for WebBrowserDocumentCompleted, it does seem the Url property is only set in the DocumentCompleted, you can see more there.
Please note: you must register the DocumentCompleted event first before setting the Url property as when you do, it will navigate first and you will not receive the DocumentCompleted event.
I was able to find out why it did not want to function, at least I hope so. The "hello.html" file contained calls to jquery and THREE.js, while WebBroser seems not to support the latter. Therefore I did not see any content in the control. After I threw out THREE.js and inserted most simple HTML code, it worked just OK! Now I am busy trying to bring WebBrowser to support THREE.js (there exists a skeptical opinion about this, though).

Selenium Webdriver unable to access web element on Internet Explorer 8 - shown as disabled

Setup Details:
Webdriver 2.39
IEDriverServer 2.39
I'm running Selenium automation on an internal site. The code works fine on Firefox 27 but there's an issue on IE8
I'm trying to first clear and enter text in a text field on IE. This fails on IE with the error "Element must not be hidden, disabled or read-only." I checked the element properties on IE and it does indeed show enabled as False, even though the element is plainly available. On Firefox, enabled is correctly set to True.
I've tried to use Xpath and sendkeys but they don't work. Here what I tried:
driver.FindElement(By.XPath("//input[#name='tagName']")).Clear(); - not working
driver.FindElement(By.XPath("//input[#name='tagName']")).SendKeys(tagName); - not working
driver.FindElement(By.Id("tagName")).SendKeys(Keys.Control); - not working
driver.FindElement(By.Id("tagName")).Clear(); - not working
driver.FindElement(By.Id("tagName")).SendKeys(tagName); - not working
Is there some way I can access this element on IE?
Thanks,
J.
We frequently test against IE8 and encounter "unique" Selenium issues.
Sometimes we use ExecuteScript to bypass Selenium's finicky selectors, and use jQuery to return the element or to manipulate it directly:
// Get an element
IWebElement element = (IWebElement) driver.ExecuteScript("return $('#tagName')[0]");
// Clear the value of a field
driver.ExecuteScript("$('input[name=\'tagName\']').val('');");
The best solution was the builder object of Selenium. I used this to force the automation to select the textbox and enter test like so:
IWebElement searchField = Global.driver.FindElement(by);
builder.Click(searchField).SendKeys(searchField, textToEnter).Perform();
This worked!
J.
WebElement searchField = Global.driver.FindElement(by);
builder.Click(searchField).SendKeys(searchField, textToEnter).Perform();
****its working but sending wrong text to the field.
For ex: i have to send "11-12-2015" and it is sending "28-12-2015".
Any Clue what's happening when performing inserting action.****

How to click on a link using Webkit Browser?

I want to click on link after navigating to a website
webKitBrowser1.Navigate("http://www.somesite.com");
How to click on a link on this website assuming that the link's id is lnkId ?
Go to Google
In the default browser control that comes with Visual Studio, I can do that using the code below :
foreach (HtmlElement el in webBrowser1.Document.GetElementTagName("a")) {
if (el.GetAttribute("id") == "lnkId") {
el.InvokeMember("click");
}
}
What is the equivalent of the code above when I'm using WebkitDotNet control?
As the WebKit doesn't provide a Click() event (see here for details), you cannot do that in the above way. But a small trick may work as an equivalent of the original winforms way as below:
foreach (Node el in webKitBrowser1.Document.GetElementsByTagName("a"))
{
if (((Element) el).GetAttribute("id") == "lnkId")
{
string urlString = ((Element) el).Attributes["href"].NodeValue;
webKitBrowser1.Navigate(urlString);
}
}
Here what I am doing is casting the WebKit.DOM.Node object to its subclass WebKit.DOM.Element to get its Attributes. Then providing href to the NamedNodeMap, i.e. Attributes as the NodeName, you can easily extract the NodeValue, which is the target url in this case. You can then simply invoke the Navigate(urlString) method on the WebKitBrowser instance to replicate the click event.
I don't work with Windows and all my experience is on Webkit GTK. Following comments are based on that experience.
I am not sure which webkit .NET version you are using. Looks like there are multiple implementations. Assuming you are using the one mentioned by Wasif, you can evaluate javascript as mentioned in the example https://code.google.com/p/open-webkit-sharp/source/browse/JavaScriptExample/Form1.cs.
Actually if implementation is supporting javascript execution then you can do most, if not all the DOM operations. The API functions are usually same as javascript functions and most of the time call exact same functions internally despite of origination. Communication between your application and javascript can be little challenging, but if you can read alert messages, that also can be solved. It looks like this library does support alert handling mechanism. A tool I wrote at https://github.com/nhrdl/notesMD will show some examples of achieving this communication though it uses GTK version and is written in python.
Incidentally if you know the id of the element, then Document.GetElementById will save you the loop.
webKitBrowser1.StringByEvaluatingJavaScriptFromString("var inpt = document.createElement(\"input\"); inpt.setAttribute(\"type\", \"submit\"); inpt.setAttribute(\"id\", \"nut\"); inpt.setAttribute(\"type\", \"submit\"); inpt.setAttribute(\"name\", \"tmp\"); inpt.setAttribute(\"value\", \"tmp\"); var element = document.getElementById(\"lnk\"); element.appendChild(inpt);");
webKitBrowser1.StringByEvaluatingJavaScriptFromString("document.getElementById('nut').click();");

Silverlight passing an array to a web page's dialog arguments

I have the following line of code to open a web page modal dialog in C# (Silverlight):
var so = (ScriptObject)HtmlPage.Window.Invoke(
"showModalDialog",
modalWindowUrl,
dialogArgs,
"dialogWidth:600px;dialogHeight:600px;");
Now, code similar to the following is being called on the page I am displaying, and I need to make sure it gets the values I'm trying to pass in (this is a MSCRM web page I don't have control over):
dialogArgs.items <-- will be an array I pass in
dialogArgs.items[i].getAttribute("oid") <-- will return something
dialogArgs.items[i].getAttribute("otype") <-- will return something
dialogArgs.items[i].values <-- will return something
What I have tried to send in (from my C# code) is this:
dialogArgs = #"{items:[{oid:" + id + ",otype:" + type + "}]}";
which will result in a JSON string... but I'm guessing this just ends up as a string within the JavaScript and not a JSON object.
Any ideas how I get this to work?
A few side notes:
I can't get IE to debug the modal dialog that results from this call. I can get the debugging tools displaying, but it won't attach to the page because it cannot refresh it.
I don't have control over this modal dialog. It's a page that is displayed using MS Dynamics CRM. For that reason I cannot mess with the JavaScript or anything to test stuff.
Looks like I won the tumbleweed award for this one! Can't believe how uncommon this scenario seems to be. The solution ended up being quite simple, but not very documented so took me a while to track down. Thought I would share here.
Firstly, a quick search across the internet reveals that we can set this up using the following:
var dialogArgs = HtmlPage.Window.CreateInstance("Object");
Which gives you a ScriptObject back. For properties:
dialogArgs.SetProperty("items", items);
Some code for setting up an array and an item should look something like this (I have just created a new GUID for the purpose of this example):
var item = HtmlPage.Window.CreateInstance("Object");
item.SetProperty("oid", Guid.NewGuid());
item.SetProperty("otype", "account");
var items = HtmlPage.Window.CreateInstance("Object");
items.SetProperty(0, item);
And finally, just pass that object straight into your dialog window like this:
var so = (ScriptObject)HtmlPage.Window.Invoke("showModalDialog", lookUpWindow, dialogArgs, "dialogWidth:600px;dialogHeight:600px;");

Webbrowser control is not showing Html but shows webpage

I am automating a task using webbrowser control , the site display pages using frames.
My issue is i get to a point , where i can see the webpage loaded properly on the webbrowser control ,but when it gets into the code and i see the html i see nothing.
I have seen other examples here too , but all of those do no return all the browser html.
What i get by using this:
HtmlWindow frame = webBrowser1.Document.Window.Frames[1];
string str = frame.Document.Body.OuterHtml;
Is just :
The main frame tag with attributes like SRC tag etc, is there any way how to handle this?Because as i can see the webpage completely loaded why do i not see the html?AS when i do that on the internet explorer i do see the pages source once loaded why not here?
ADDITIONAL INFO
There are two frames on the page :
i use this to as above:
HtmlWindow frame = webBrowser1.Document.Window.Frames[0];
string str = frame.Document.Body.OuterHtml;
And i get the correct HTMl for the first frame but for the second one i only see:
<FRAMESET frameSpacing=1 border=1 borderColor=#ffffff frameBorder=0 rows=29,*><FRAME title="Edit Search" marginHeight=0 src="http://web2.westlaw.com/result/dctopnavigation.aspx?rs=WLW12.01&ss=CXT&cnt=DOC&fcl=True&cfid=1&method=TNC&service=Search&fn=_top&sskey=CLID_SSSA49266105122&db=AK-CS&fmqv=s&srch=TRUE&origin=Search&vr=2.0&cxt=RL&rlt=CLID_QRYRLT803076105122&query=%22LAND+USE%22&mt=Westlaw&rlti=1&n=1&rp=%2fsearch%2fdefault.wl&rltdb=CLID_DB72585895122&eq=search&scxt=WL&sv=Split" frameBorder=0 name=TopNav marginWidth=0 scrolling=no><FRAME title="Main Document" marginHeight=0 src="http://web2.westlaw.com/result/dccontent.aspx?rs=WLW12.01&ss=CXT&cnt=DOC&fcl=True&cfid=1&method=TNC&service=Search&fn=_top&sskey=CLID_SSSA49266105122&db=AK-CS&fmqv=s&srch=TRUE&origin=Search&vr=2.0&cxt=RL&rlt=CLID_QRYRLT803076105122&query=%22LAND+USE%22&mt=Westlaw&rlti=1&n=1&rp=%2fsearch%2fdefault.wl&rltdb=CLID_DB72585895122&eq=search&scxt=WL&sv=Split" frameBorder=0 borderColor=#ffffff name=content marginWidth=0><NOFRAMES></NOFRAMES></FRAMESET>
UPDATE
The two url of the frames are as follows :
Frame1 whose html i see
http://web2.westlaw.com/nav/NavBar.aspx?RS=WLW12.01&VR=2.0&SV=Split&FN=_top&MT=Westlaw&MST=
Frame2 whose html i do not see:
http://web2.westlaw.com/result/result.aspx?RP=/Search/default.wl&action=Search&CFID=1&DB=AK%2DCS&EQ=search&fmqv=s&Method=TNC&origin=Search&Query=%22LAND+USE%22&RLT=CLID%5FQRYRLT302424536122&RLTDB=CLID%5FDB6558157526122&Service=Search&SRCH=TRUE&SSKey=CLID%5FSSSA648523536122&RS=WLW12.01&VR=2.0&SV=Split&FN=_top&MT=Westlaw&MST=
And the properties of the second frame whose html i do not get are in the picture below:
Thank you
I paid for the solution of the question above and it works 100 %.
What i did was use this function below and it returned me the count to the tag i was seeking which i could not find :S.. Use this to call the function listed below:
FillFrame(webBrowser1.Document.Window.Frames);
private void FillFrame(HtmlWindowCollection hwc)
{
if (hwc == null) return;
foreach (HtmlWindow hw in hwc)
{
HtmlElement getSpanid = hw.Document.GetElementById("mDisplayCiteList_ctl00_mResultCountLabel");
if (getSpanid != null)
{
doccount = getSpanid.InnerText.Replace("Documents", "").Replace("Document", "").Trim();
break;
}
if (hw.Frames.Count > 0) FillFrame(hw.Frames);
}
}
Hope it helps people .
Thank you
For taking html you have to do it that way:
WebClient client = new WebClient();
string html = client.DownloadString(#"http://stackoverflow.com");
That's an example of course, you can change the address.
By the way, you need using System.Net;
This works just fine...gets BODY element with all inner elements:
Somewhere in your Form code:
wb.Url = new Uri("http://stackoverflow.com");
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wbDocumentCompleted);
And here is wbDocumentCompleted:
void wb1DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var yourBodyHtml = wb.Document.Body.OuterHtml;
}
wb is System.Windows.Forms.WebBrowser
UPDATE:
The same as for the document, I think that your second frame is not loaded at the time you check for it's content...You can try solutions from this link. You will have to wait for your frames to be loaded in order to see its content.
The most likely reason is that frame index 0 has the same domain name as the main/parent page, while the frame index 1 has a different domain name. Am I correct?
This creates a cross-frame security issue, and the WB control just leaves you high and dry and doesn't tell you what on earth went wrong, and just leaves your objects, properties and data empty (will say "No Variables" in the watch window when you try to expand the object).
The only thing you can access in this situation is pretty much the URL and iFrame properties, but nothing inside the iFrame.
Of course, there are ways to overcome teh cross-frame security issues - but they are not built into the WebBrowser control, and they are external solutions, depending on which WB control you are using (as in, .NET version or pre .NET version).
Let me know if I have correctly identified your problem, and if so, if you would like me to tell you about the solution tailored to your setup & instance of the WB control.
UPDATE: I have noticed that you're doing a .getElementByTagName("HTML")(0).outerHTML to get the HTML, all you need to do is call this on the document object, or the .body object and that should do it. MyDoc.Body.innerHTML should get the the content you want. Also, notice that there are additional iFrames inside these documents, in case that is of relevance. Can you give us the main document URL that has these two URL's in it so we / I can replicate what you're doing here? Also, not sure why you are using DomElement but you should just cast it to the native object it wants to be cast to, either a IHTMLDocument2 or the object you see in the watch window, which I think is IHTMLFrameElement (if i recall correctly, but you will know what i mean once you see it). If you are trying to use an XML object, this could be the reason why you aren't able to get the HTML content, change the object declaration and casting if there is one, and give it a go & let us know :). Now I'm curious too :).

Categories