How to get actual JavaScript value in onclick from

2020-02-23 09:04发布

问题:

I'm looking for a way to get the JavaScript code defined inside of onclick. I'm using .NET 2.0 C# Visual Studio 2005.

Example:

<span id="foo" onclick+"window.location.href='someURL'>click here</span>

My goal is to get the string "window.location.href='someURL'".

Scenario:

A user clicks on web page element, the tag shown above for instance, inside of WebBrowser control. Then the clicked tag is refereed to HtmlElement object.

In WebBrowser control I then call HtmlElement object's getAttribute("onclick"), it just gives me "System.__ComObject".

I've searched how to deal with it then found that it can be casted then get the value.

if (tag.GetAttribute("onclick").Equals("System.__ComObject"))
{
    Console.WriteLine("dom elem  >>>>>>>>>>> " + tag.DomElement.ToString());
    mshtml.HTMLSpanElementClass span = (mshtml.HTMLSpanElementClass)tag.DomElement;

    Console.WriteLine("js value ===>" + span.onclick);
}

Output:

dom elem  >>>>>>>>>>> mshtml.HTMLSpanElementClass
js value ===> System.__ComObject

As it shown, span.onclick still give me System.__ComObject, what am I doing wrong?

In Why does HtmlElement's GetAttribute() method return “mshtml.HTMLInputElementClass” instead of the attribute's value? this guy said it worked in his case, and I've followed it, but mine is somewhat not working...

UPDATE

Research, research.....

I can add reference VisualBasic.dll to my C# project then call the method to find out who is this System.__ComObject really is.

Console.WriteLine(Microsoft.VisualBasic.Information.TypeName(span.onclick));

Output:

JScriptTypeInfo

It looks like this is a JScript type... how can I access this object?

More detail

The above description is based on my current project. The project is to create something like Selenium IDE. It uses WebBrowser control instead.

Selenium IDE creates 3 different things to record an element in the web document.

1. actionType
2. xpath
3. value

For instance,

type, //input[@id=foo], "hello world"
clickAndWait, //link=login, ""

Selenium IDE recognize page load so it changes actionType between "click" and "clickAndWait". My case, I want to make it simple.

If I click on the element and if it is anchor tag or has page load kind of javascript such as onclick=window.location.href='blah' then I want to set the actionType to "clickAndWait".

回答1:

There are number of ways you can do it.

  1. There is an Event object in DOM, which will give you information about which element generated this event.
  2. You can look at here, http://msdn.microsoft.com/en-us/library/ff975965%28v=VS.85%29.aspx
  3. This one is good, you can use this easily, you will get the event object as method parameter which you can investigate parameters to find out the source of the event. http://support.microsoft.com/kb/312777

Another alternative is to use a custom navigation url and act upon it

  1. Override BeforeNavigate event
  2. Check for Navigation url if it contains "mycommand:click" or "mycommand:clickandwait" 3. If it contains any of this, then set cancel as true. (this will stop navigation by browser).
  3. Then you can navigate your webbrowser code from your C# code and pass cancel as true.

Another Alternative method is to use External object, WebBrowser allows you to set an ObjectForScripting which you can access within Javascript of HTML.

ObjectForScripting in .NET 2.0

[ComVisible(true)]
public class MyClass
{
   // can be called from JavaScript
   public void ShowMessageBox(string msg){
       MessageBox.Show(msg);
   }
}

myBrowser.ObjectForScripting = new MyClass(); 
// or you can reuse instance of MyClass

And you can call,

window.external.ShowMessageBox("This was called from JavaScript");


回答2:

Cast the element object to mshtml.IHTMLDOMNode, then read the attributes via IHTMLDOMNode.attributes. HtmlElement.GetAttribute is getting the IDispatch interface of the jscript function generated from the embedded attribute.



回答3:

You can try to parse webBrowser1.DocumentText property using HtmlAgilityPack and then get desired result using XPath.



回答4:

If you don't HAVE to do it with C# (you can do it with JS and create a Postback) you should take a look at THIS question.



回答5:

As per Sheng Jiang's response, here is some working sample:

IHTMLElement element = YourCodeToGetElement();
string onclick = string.Empty;

IHTMLDOMNode domNode = element as IHTMLDOMNode;
IHTMLAttributeCollection attrs = domNode.attributes;

foreach (IHTMLDOMAttribute attr in attrs)
{
    if (attr.nodeName.Equals("onclick"))
    {
        string attrValue = attr.nodeValue as string;
        if (!string.IsNullOrEmpty(attrValue))
        {
            onclick = attr.nodeValue;
            break;
        }
    }
}


回答6:

You can parse it yourself easily, by first reading obj.outerHtml. That should give you the entire html for that obj, then search it for the value onclick="????" and extract the ???? part.