如何在 WebBrowser 控件中注入 Javascript?

IT技术 c# javascript .net winforms webbrowser-control
2021-01-09 22:48:35

我试过这个:

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 中?

6个回答

由于某种原因,Richard 的解决方案对我不起作用(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界面引入到你的项目中。

添加对本地js文件的引用怎么样?请参阅stackoverflow.com/questions/4029602/...
2021-03-10 22:48:35
这也适用于注入 jquery 文件吗?
2021-03-13 22:48:35
酷,我认为 IHTMLScriptElement 的使用使代码意图在任何情况下都更加明显。我确实想知道为什么您会遇到异常,但有时会与 COM 互操作性发生冲突。
2021-03-30 22:48:35
请帮我解决一下这个。你是怎么做到的。我想通过我的 C++ 应用程序将 JS 实时注入我的页面。我该怎么办。
2021-04-05 22:48:35
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 程序集。
2021-03-17 22:48:35
@jsight 这应该是公认的答案。它与当前答案相同,但更简单且没有IHTMLSCriptElement依赖性。
2021-03-20 22:48:35

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

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 参考

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

dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
@justin.m.chase 你救了我的命。
2021-03-25 22:48:35
这基本上正是动态关键字的重点:COM 互操作。你这里实际上没有类型推断,你有文档。例如,因为 IHTMLElement2 不能从 IHtmlElement 分配,并且在运行时您只有一个 COM 代理对象。您只需要知道将哪些接口转换为哪些接口即可。dynamic 关键字可以帮助您减少大量繁琐的工作。您知道该方法存在为什么将其转换为某个接口?它并不完全是“调用 DLR”,它只是生成知道如何调用 COM 对象上的方法的代码(在本例中)。
2021-03-30 22:48:35
为什么有人需要动态呢?如果您想节省一些输入,我们从 C# 3.0 开始就有类型推断,所以 var 是可以接受的。无需开始调用 DLR。
2021-04-04 22:48:35

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

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

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