如何在WebBrowser控件中注入Javascript?

我试过这个:

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?

出于某种原因理查德的解决scheme没有在我的工作(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中testing)

编辑:修正function集中的大小写问题。

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

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

这是我在工作之后find的最简单的方法:

 string jCode = "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[] { jCode }); 

eval(str)所做的全局JavaScript函数是parsing并执行str中写入的内容。 在这里检查w3schools 。

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

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

我想这不会“注入”它,但它会运行你的function,如果这就是你以后。 (以防万一你把这个问题搞得太复杂了。)如果你能弄清楚如何注入javascript,把它放到函数“foo”的主体中,让javascript为你做注入。

HTML文档的托pipe包装并没有完全实现你需要的function,所以你需要深入到MSHTML API来完成你想要的东西:

1)添加一个对MSHTML的引用,它将在COM引用下被称为“Microsoft HTML Object Library”。

2)添加“使用mshtml;” 到你的名字空间。

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

 IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement; 

4)调用insertAdjacentText方法,第一个参数值为“afterBegin”。 所有可能的值在这里列出:

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

5)现在你将能够看到scriptEl.InnerText属性中的代码。

理查德

这是一个使用mshtml的解决scheme

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

我相信最简单的方法来从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控件有效。

这个解决scheme不是跨浏览器,因为“execScript”只在IE和Chrome中定义。 但问题是关于微软WebBrowser控件和IE是唯一支持的。

要获得有效的跨浏览器方法来注入JavaScript代码,请使用新的关键字创build一个Function对象。 这个例子通过注入代码创build一个匿名函数并执行它(javascript实现了闭包,函数可以访问全局空间而没有局部variables污染)。

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

当然,你可以延迟执行:

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

希望它有帮助

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

 [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"); } } } } 

我用这个:D

 HtmlElement script = this.WebNavegador.Document.CreateElement("SCRIPT"); script.SetAttribute("TEXT", "function GetNameFromBrowser() {" + "return 'My name is David';" + "}"); this.WebNavegador.Document.Body.AppendChild(script); 

然后你可以执行并得到结果:

 string myNameIs = (string)this.WebNavegador.Document.InvokeScript("GetNameFromBrowser"); 

我希望能有所帮助

您始终可以使用“DocumentStream”或“DocumentText”属性。 为了处理HTML文档,我推荐使用HTML Agility Pack 。

这里是一个VB.Net的例子,如果您试图检索WebBrowser控件中加载页面内的variables的值。

步骤1)将您的项目中的COM引用添加到Microsoft HTML对象库

步骤2)接下来,将此VB.Net代码添加到您的Form1以导入mshtml库:
导入mshtml

步骤3)在“公共类Form1”行上添加此VB.Net代码:
<System.Runtime.InteropServices.ComVisibleAttribute(真)>

步骤4)将WebBrowser控件添加到您的项目

步骤5)将此VB.Net代码添加到您的Form1_Load函数:
WebBrowser1.ObjectForScripting =我

第6步)添加这个VB.Net子将注入一个函数“CallbackGetVar”到网页的Javascript:

  Public Sub InjectCallbackGetVar(ByRef wb As WebBrowser) Dim head As HtmlElement Dim script As HtmlElement Dim domElement As IHTMLScriptElement head = wb.Document.GetElementsByTagName("head")(0) script = wb.Document.CreateElement("script") domElement = script.DomElement domElement.type = "text/javascript" domElement.text = "function CallbackGetVar(myVar) { window.external.Callback_GetVar(eval(myVar)); }" head.AppendChild(script) End Sub 

第7步)添加下面的VB.Net子,然后在调用Javascript时寻找:

  Public Sub Callback_GetVar(ByVal vVar As String) Debug.Print(vVar) End Sub 

第8步)最后,要调用Javascriptcallback,请在按下button时添加此VB.Net代码,或者您喜欢的任何位置:

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click WebBrowser1.Document.InvokeScript("CallbackGetVar", New Object() {"NameOfVarToRetrieve"}) End Sub 

第9步)如果它让你感到惊讶,那么你可能需要阅读第6步中使用的Javascript“eval”函数,这是可能的。 它将接收一个string,并确定一个variables是否以该名称存在,如果是,则返回该variables的值。

你想要做的是使用Page.RegisterStartupScript(key,script):

详情请参阅: http : //msdn.microsoft.com/en-us/library/aa478975.aspx

你基本上做的是build立你的JavaScriptstring,传递给该方法,并给它一个唯一的ID(如果你尝试在一个页面上注册两次)。

编辑:这就是你所说的触发快乐。 随意下来吧。 🙂

如果你需要注入一个完整的文件,那么你可以使用这个:

 With Browser.Document' 'Dim Head As HtmlElement = .GetElementsByTagName("head")(0)' 'Dim Script As HtmlElement = .CreateElement("script")' 'Dim Streamer As New StreamReader(<Here goes path to file as String>)' 'Using Streamer' 'Script.SetAttribute("text", Streamer.ReadToEnd())' 'End Using' 'Head.AppendChild(Script)' '.InvokeScript(<Here goes a method name as String and without parentheses>)' 'End With' 

请记得导入System.IO以使用StreamReader。 我希望这对你有所帮助