当前位置:  开发笔记 > 编程语言 > 正文

如何在WebBrowser控件中注入Javascript?

如何解决《如何在WebBrowser控件中注入Javascript?》经验,为你挑选了9个好方法。

我试过这个:

string newScript = textBox1.Text;
HtmlElement head = browserCtrl.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = browserCtrl.Document.CreateElement("script");
lblStatus.Text = scriptEl.GetType().ToString();
scriptEl.SetAttribute("type", "text/javascript");
head.AppendChild(scriptEl);
scriptEl.InnerHtml = "function sayHello() { alert('hello') }";

scriptEl.InnerHtml和scriptEl.InnerText都给出了错误:

System.NotSupportedException: Property is not supported on this type of HtmlElement.
   at System.Windows.Forms.HtmlElement.set_InnerHtml(String value)
   at SForceApp.Form1.button1_Click(Object sender, EventArgs e) in d:\jsight\installs\SForceApp\SForceApp\Form1.cs:line 31
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

是否有一种简单的方法将脚本注入dom?



1> Atanas Korch..:

出于某种原因,理查德的解决方案在我的结尾不起作用(insertAdjacentText因异常而失败).然而,这似乎有效:

HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
element.text = "function sayHello() { alert('hello') }";
head.AppendChild(scriptEl);
webBrowser1.Document.InvokeScript("sayHello");

这个答案解释了如何让IHTMLScriptElement界面进入你的项目.



2> typpo..:
HtmlDocument doc = browser.Document;
HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayHello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");

(在.NET 4/Windows Forms App中测试)

编辑:修复了函数集中的案例问题.


我很欣赏这个解决方案,因为它不依赖于(虽然有用!)IHTMLSCriptElement程序集.
@jsight这应该是公认的答案.它与当前答案相同,但更简单,没有`IHTMLSCriptElement`依赖.

3> 小智..:

这是我在完成此工作后找到的最简单的方法:

string javascript = "alert('Hello');";
// or any combination of your JavaScript commands
// (including function calls, variables... etc)

// WebBrowser webBrowser1 is what you are using for your web browser
webBrowser1.Document.InvokeScript("eval", new object[] { javascript });

全局JavaScript函数的eval(str)作用是解析和执行str中编写的任何内容.在这里查看w3schools ref.



4> justin.m.cha..:

此外,在.NET 4中,如果使用dynamic关键字,则更容易:

dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);


这基本上是动态关键字的重点:COM互操作.这里你实际上没有Type Inference,你有文档.例如,因为IHTMLElement2不能从IHtmlElement分配,并且在运行时您只有一个COM代理对象.您只需知道要将哪些接口转换为什么.动态关键字可以帮助您减少很多错误.你知道该方法存在为何将其转换为某个界面?它并不完全"调用DLR"它只生成知道如何在COM对象上调用方法的代码(在本例中).
为什么有人需要动态呢?如果你试图保存一些打字,我们确实有类型推断,因为C#3.0所以var是可以接受的.无需开始调用DLR.

5> Eyal..:

如果您真正想要的是运行javascript,这将是最简单的(VB .Net):

MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")

我想这不会"注入"但它会运行你的功能,如果这就是你所追求的.(以防万一你过度复杂的问题.)如果你能弄清楚如何注入javascript,把它放到函数"foo"的主体中,让javascript为你做注入.



6> ZeroBugBounc..:

HTML文档的托管包装器并不能完全实现您需要的功能,因此您需要深入了解MSHTML API以实现您的目标:

1)添加对MSHTML的引用,它将在COM引用下被称为"Microsoft HTML Object Library" .

2)添加'using mshtml;' 到您的命名空间.

3)获取对脚本元素的IHTMLElement的引用:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4)调用insertAdjacentText方法,第一个参数值为"afterBegin".此处列出了所有可能的值:

iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");

5)现在,您将能够在scriptEl.InnerText属性中看到代码.

理查德



7> 小智..:

我相信从c#在WebBrowser控件HTML文档中注入Javascript的最简单的方法是调用"execStrip"方法,并将代码作为参数注入.

在此示例中,javascript代码在全局范围内注入并执行:

var jsCode="alert('hello world from injected code');";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });

如果要延迟执行,请注入函数并在以下情况后调用它们:

var jsCode="function greet(msg){alert(msg);};";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
...............
WebBrowser.Document.InvokeScript("greet",new object[] {"hello world"});

这适用于Windows窗体和WPF WebBrowser控件.

此解决方案不是跨浏览器,因为"execScript"仅在IE和Chrome中定义.但问题是关于Microsoft WebBrowser控件和IE是唯一支持的.

对于有效的跨浏览器方法来注入javascript代码,请使用新的关键字创建一个Function对象.此示例使用注入的代码创建一个匿名函数并执行它(javascript实现闭包,函数可以访问全局空间而不会出现局部变量污染).

var jsCode="alert('hello world');";
(new Function(code))();

当然,你可以延迟执行:

var jsCode="alert('hello world');";
var inserted=new Function(code);
.................
inserted();

希望能帮助到你



8> Uwe Keim..:

作为已接受答案的后续内容,这是IHTMLScriptElement接口的最小定义,不需要包含其他类型库:

[ComImport, ComVisible(true), Guid(@"3050f28b-98b5-11cf-bb82-00aa00bdce0b")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(TypeLibTypeFlags.FDispatchable)]
public interface IHTMLScriptElement
{
    [DispId(1006)]
    string text { set; [return: MarshalAs(UnmanagedType.BStr)] get; }
}

因此,WebBrowser控件派生类中的完整代码如下所示:

protected override void OnDocumentCompleted(
    WebBrowserDocumentCompletedEventArgs e)
{
    base.OnDocumentCompleted(e);

    // Disable text selection.
    var doc = Document;
    if (doc != null)
    {
        var heads = doc.GetElementsByTagName(@"head");
        if (heads.Count > 0)
        {
            var scriptEl = doc.CreateElement(@"script");
            if (scriptEl != null)
            {
                var element = (IHTMLScriptElement)scriptEl.DomElement;
                element.text =
                    @"function disableSelection()
                    { 
                        document.body.onselectstart=function(){ return false; }; 
                        document.body.ondragstart=function() { return false; };
                    }";
                heads[0].AppendChild(scriptEl);
                doc.InvokeScript(@"disableSelection");
            }
        }
    }
}



9> Camilo Sanch..:

这是一个使用mshtml的解决方案

IHTMLDocument2 doc = new HTMLDocumentClass();
doc.write(new object[] { File.ReadAllText(filePath) });
doc.close();

IHTMLElement head = (IHTMLElement)((IHTMLElementCollection)doc.all.tags("head")).item(null, 0);
IHTMLScriptElement scriptObject = (IHTMLScriptElement)doc.createElement("script");
scriptObject.type = @"text/javascript";
scriptObject.text = @"function btn1_OnClick(str){
    alert('you clicked' + str);
}";
((HTMLHeadElementClass)head).appendChild((IHTMLDOMNode)scriptObject);


两年后我害怕
由于这是一个社区资源,他的答案对其他人(如我自己)仍然有用.为mshtml等效的+1,给我一个问题.
推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有