Can't call method of a JavaScript object created in code injected to WebBrowser's Document after navigating

痴心易碎 提交于 2019-12-23 03:48:07

问题


I've found some other questions like this, but not exactly, and with solutions that doesn't solve this particular problem. I'm working on a project that is something like iMacros for Internet Explorer. This is my simplified code:

public partial class Form1 : Form
{
    public JSObject jsObject = new JSObject();
    int uniqueNameEnsurer = 0;

    public Form1()
    {
        InitializeComponent();
        webBrowser1.Navigate("www.google.com");
    }

    private void InvokeCode(string functionCode)
    {
        HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
        HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
        IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
        element.text = "function MyInjectedFunction" + uniqueNameEnsurer + "(Param){" + functionCode + "}";
        head.AppendChild(scriptEl);
        webBrowser1.Document.InvokeScript("MyInjectedFunction" + uniqueNameEnsurer, new object[] { jsObject });
        uniqueNameEnsurer++;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        InvokeCode(@"
            function MyObject()
            {
                this.Something = 'hello';
                this.SomeFunc = function(){
                    alert('in SomeFunc!!!');
                }
            }

            Param.UserData = new MyObject();
        ");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        webBrowser1.Navigate("www.bing.com");
    }

    private void button3_Click(object sender, EventArgs e)
    {
        InvokeCode(@"
            alert(Param.UserData.Something);
            Param.UserData.SomeFunc();
        ");
    }
}

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class JSObject
{
    public object UserData;
}

So, what I do is, click button1 (which calls button1_Click), then button2 (which calls button2_Click), wait a sec to load, and then click button3 (which calls button3_Click). When I click button3, I get an alert saying "hello" (which means the object somehow persists after navigating), but right after that, I get an error saying “Can't execute code from a freed script”. This is probably some kind of security thing. I've found some posts talking about but none of them solve my problem. I can do a work around by creating my SomeFunc as a string and then using eval, but this is a nasty solution. If there is anything I can do to my C# code that would let me keep the JavaScript code just the way it is (and work, of course), it would be super cool. If not, what would be the best work around so that I can call SomeFunc after navigating?


回答1:


There are a few things going on here that I don't quite understand. First off I wouldn't count on scripts being there after a call to Navigate. Once you navigate I think you should re-inject all your scripts that you want.

Second I'm not seeing where "MyObject" is defined? I see "new MyObject();" in your script there but I don't see the MyObject function defined anywhere so it doesn't surprise me that your SomeFunc() is not defined. Assuming that the sample is just incomplete.

And finally you should look into implementing IReflect and IExpando on your JSObject. It might solve all your problems.




回答2:


OK, apparently it is just NOT possible to do what I'm trying to do with just C#. I will need to implement some kind of object serialization and deserialization system in JavaScript and serialize the the UserData before navigating and deserialize it after navigating.



来源:https://stackoverflow.com/questions/5009189/cant-call-method-of-a-javascript-object-created-in-code-injected-to-webbrowser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!