82

我试过这个:

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

4

15 回答 15

102

由于某种原因,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界面引入您的项目。

于 2008-09-30T19:11:43.033 回答
52
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 窗体应用程序中测试)

编辑:修复了功能集中的案例问题。

于 2011-06-03T02:33:40.940 回答
33

这是我在处理此问题后发现的最简单的方法:

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

于 2011-12-31T07:49:53.823 回答
22

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

dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
于 2010-06-16T22:03:28.120 回答
17

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

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

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

于 2010-02-15T20:57:02.823 回答
10

HTML 文档的托管包装器并没有完全实现您需要的功能,因此您需要深入了解 MSHTML API 来完成您想要的功能:

1) 添加对 MSHTML 的引用,在COM引用下可能将其称为“Microsoft HTML 对象库”。

2) 添加'使用 mshtml;' 到您的命名空间。

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

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

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

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

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

Hth,理查德

于 2008-09-30T18:28:58.283 回答
9

我相信从 c# 在 WebBrowser Control HTML 文档中注入 Javascript 的最简单方法是使用要注入的代码作为参数调用“execScript”方法。

在此示例中,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();

希望能帮助到你

于 2011-10-18T01:42:36.173 回答
8

作为已接受答案的后续,这是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");
            }
        }
    }
}
于 2012-04-14T13:22:47.953 回答
7

这是使用 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);
于 2010-08-17T20:11:12.213 回答
2

这是一个 VB.Net 示例,如果您尝试从 WebBrowser 控件中加载的页面中检索变量的值。

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

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

步骤 3) 在“Public Class Form1”行上方添加此 VB.Net 代码:
<System.Runtime.InteropServices.ComVisibleAttribute(True)>

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

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

第 6 步)添加这个 VB.Net 子程序,它将向网页的 Javascript 中注入一个函数“CallbackGetVar”:

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 步)最后,要调用 Javascript 回调,请在按下按钮时添加此 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”函数,这就是使这成为可能的原因。它将接受一个字符串并确定是否存在具有该名称的变量,如果存在,则返回该变量的值。

于 2011-11-16T19:01:52.887 回答
2

我用过这个: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");

我希望能有所帮助

于 2016-07-19T12:47:45.660 回答
1

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

于 2008-09-30T16:09:16.090 回答
1

我用这个:

webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
于 2018-05-28T02:45:57.023 回答
0

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

有关详细信息,请参见此处:http: //msdn.microsoft.com/en-us/library/aa478975.aspx

您基本上要做的是构建您的 javascript 字符串,将其传递给该方法并给它一个唯一的 id(以防您尝试在页面上注册两次。)

编辑:这就是你所说的触发快乐。随意放下它。:)

于 2008-09-30T16:07:32.227 回答
0

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

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. 我希望这有帮助。

于 2014-11-08T02:52:57.370 回答