【问题标题】:Can't call method of a JavaScript object created in code injected to WebBrowser's Document after navigating导航后无法调用在注入到 WebBrowser 文档的代码中创建的 JavaScript 对象的方法
【发布时间】:2011-06-27 21:47:52
【问题描述】:

我发现了一些其他类似的问题,但不完全是这样,并且解决方案不能解决这个特定问题。我正在开发一个类似于 iMacros for Internet Explorer 的项目。这是我的简化代码:

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;
}

所以,我要做的是,单击 button1(调用 button1_Click),然后单击 button2(调用 button2_Click),等待一秒加载,然后单击 button3(调用 button3_Click)。 当我单击按钮 3 时,我收到一条警告说“你好”(这意味着该对象在导航后以某种方式仍然存在),但在那之后,我收到一条错误消息“无法从已释放的脚本中执行代码”。这可能是某种安全问题。我发现一些帖子在谈论,但没有一个能解决我的问题。我可以通过将SomeFunc 创建为字符串然后使用eval 来解决问题,但这是一个讨厌的解决方案。如果我可以对我的 C# 代码做任何事情,让我的 JavaScript 代码保持原样(当然可以工作),那将是非常酷的。如果没有,最好的解决方法是什么,以便我可以在导航后致电SomeFunc

【问题讨论】:

  • 我想我可以通过将对象序列化为字符串来解决这个问题,但是方法也需要序列化,不知道最好的方法是什么。

标签: c# javascript dom browser


【解决方案1】:

这里发生了一些我不太明白的事情。首先,在调用 Navigate 之后,我不会指望脚本在那里。一旦你导航,我认为你应该重新注入你想要的所有脚本。

其次,我没有看到“MyObject”是在哪里定义的?我看到“新的 MyObject();”在你的脚本中,但我没有看到 MyObject 函数在任何地方定义,所以你的 SomeFunc() 没有定义并不让我感到惊讶。假设样本不完整。

最后,您应该考虑在您的 JSObject 上实现 IReflect 和 IExpando。它可能会解决你所有的问题。

【讨论】:

  • MyObject 是在第一次调用 JavaScript 代码时定义的,并创建了一个 MyObject 实例并将其传递回我的 C# 应用程序,然后传递回第二次 JavaScript 调用。在调用 Navigate 后,我不指望脚本在那里。他们不会的。但我希望对象的实例在导航之后以某种方式持续存在。
【解决方案2】:

好的,显然不可能只用 C# 来做我想做的事情。我将需要在 JavaScript 中实现某种对象序列化和反序列化系统,并在导航之前序列化 UserData,并在导航后对其进行反序列化。

【讨论】:

    猜你喜欢
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多