我试过这个:
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?
出于某种原因,理查德的解决方案在我的结尾不起作用(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
界面进入你的项目.
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中测试)
编辑:修复了函数集中的案例问题.
这是我在完成此工作后找到的最简单的方法:
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.
此外,在.NET 4中,如果使用dynamic关键字,则更容易:
dynamic document = this.browser.Document; dynamic head = document.GetElementsByTagName("head")[0]; dynamic scriptEl = document.CreateElement("script"); scriptEl.text = ...; head.AppendChild(scriptEl);
如果您真正想要的是运行javascript,这将是最简单的(VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
我想这不会"注入"但它会运行你的功能,如果这就是你所追求的.(以防万一你过度复杂的问题.)如果你能弄清楚如何注入javascript,把它放到函数"foo"的主体中,让javascript为你做注入.
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属性中看到代码.
理查德
我相信从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();
希望能帮助到你
作为已接受答案的后续内容,这是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"); } } } }
这是一个使用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);