简体   繁体   English

如何在 WebBrowser 控件中注入 Javascript?

[英]How to inject Javascript in WebBrowser control?

I've tried this:我试过这个:

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 and scriptEl.InnerText both give errors: 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)

Is there an easy way to inject a script into the dom?有没有一种简单的方法可以将脚本注入到 dom 中?

For some reason Richard's solution didn't work on my end (insertAdjacentText failed with an exception).由于某种原因,Richard 的解决方案对我不起作用(insertAdjacentText 因异常而失败)。 This however seems to work:然而,这似乎有效:

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

This answer explains how to get the IHTMLScriptElement interface into your project.这个答案解释了如何将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");

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

Edit: Fixed case issue in function set.编辑:修复了函数集中的大小写问题。

Here is the easiest way that I found after working on this:这是我在完成此工作后发现的最简单的方法:

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

What global JavaScript function eval(str) does is parses and executes whatever is written in str. JavaScript 全局函数eval(str)所做的是解析并执行 str 中写入的任何内容。 Check w3schools ref here .在此处查看w3schools 参考

Also, in .NET 4 this is even easier if you use the dynamic keyword:此外,在 .NET 4 中,如果您使用 dynamic 关键字,这会更容易:

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

If all you really want is to run javascript, this would be easiest (VB .Net):如果您真正想要的是运行 javascript,这将是最简单的(VB .Net):

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

I guess that this wouldn't "inject" it but it'll run your function, if that's what you're after.我想这不会“注入”它,但它会运行您的功能,如果这就是您所追求的。 (Just in case you've over-complicated the problem.) And if you can figure out how to inject in javascript, put that into the body of the function "foo" and let the javascript do the injection for you. (以防万一你把问题复杂化了。)如果你能弄清楚如何在 javascript 中注入,把它放到函数“foo”的主体中,让 javascript 为你做注入。

The managed wrapper for the HTML document doesn't completely implement the functionality you need, so you need to dip into the MSHTML API to accomplish what you want: HTML 文档的托管包装器并没有完全实现您需要的功能,因此您需要深入了解 MSHTML API 来完成您想要的:

1) Add a reference to MSHTML, which will probalby be called "Microsoft HTML Object Library" under COM references. 1) 添加对 MSHTML 的引用,在COM引用下,它可能被称为“Microsoft HTML 对象库”。

2) Add 'using mshtml;' 2) 添加'使用 mshtml;' to your namespaces.到您的命名空间。

3) Get a reference to your script element's IHTMLElement: 3) 获取对脚本元素的 IHTMLElement 的引用:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4) Call the insertAdjacentText method, with the first parameter value of "afterBegin". 4)调用insertAdjacentText方法,第一个参数值为“afterBegin”。 All the possible values are listed here : 此处列出所有可能的值:

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

5) Now you'll be able to see the code in the scriptEl.InnerText property. 5) 现在您将能够看到 scriptEl.InnerText 属性中的代码。

Hth, Richard呃,理查德

As a follow-up to the accepted answer , this is a minimal definition of the IHTMLScriptElement interface which does not require to include additional type libraries:作为已接受答案的后续,这是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; }
}

So a full code inside a WebBrowser control derived class would look like:因此,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");
            }
        }
    }
}

I believe the most simple method to inject Javascript in a WebBrowser Control HTML Document from c# is to invoke the "execScript" method with the code to be injected as argument.我相信从 c# 在 WebBrowser Control HTML 文档中注入 Javascript 的最简单方法是使用要注入的代码作为参数调用“execScript”方法。

In this example the javascript code is injected and executed at global scope:在这个例子中,javascript 代码被注入并在全局范围内执行:

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

If you want to delay execution, inject functions and call them after:如果要延迟执行,请注入函数并在以下时间调用它们:

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

This is valid for Windows Forms and WPF WebBrowser controls.这对 Windows 窗体和 WPF WebBrowser 控件有效。

This solution is not cross browser because "execScript" is defined only in IE and Chrome.此解决方案不是跨浏览器,因为“execScript”仅在 IE 和 Chrome 中定义。 But the question is about Microsoft WebBrowser controls and IE is the only one supported.但问题是关于 Microsoft WebBrowser 控件,而 IE 是唯一受支持的控件。

For a valid cross browser method to inject javascript code, create a Function object with the new Keyword.要使用有效的跨浏览器方法来注入 javascript 代码,请使用 new 关键字创建一个 Function 对象。 This example creates an anonymous function with injected code and executes it (javascript implements closures and the function has access to global space without local variable pollution).这个例子创建了一个带有注入代码的匿名函数并执行它(javascript 实现了闭​​包并且该函数可以访问全局空间而没有局部变量污染)。

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

Of course, you can delay execution:当然,你可以延迟执行:

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

Hope it helps希望能帮助到你

this is a solution using mshtml这是使用 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);

I used this :D我用过这个:D

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

this.WebNavegador.Document.Body.AppendChild(script);

Then you can execute and get the result with:然后你可以执行并获得结果:

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

I hope to be helpful我希望能有所帮助

Here is a VB.Net example if you are trying to retrieve the value of a variable from within a page loaded in a WebBrowser control.如果您尝试从 WebBrowser 控件中加载的页面中检索变量的值,则这是一个 VB.Net 示例。

Step 1) Add a COM reference in your project to Microsoft HTML Object Library步骤 1) 将项目中的 COM 引用添加到 Microsoft HTML 对象库

Step 2) Next, add this VB.Net code to your Form1 to import the mshtml library:步骤 2) 接下来,将此 VB.Net 代码添加到您的 Form1 以导入 mshtml 库:
Imports mshtml导入 mshtml

Step 3) Add this VB.Net code above your "Public Class Form1" line:步骤 3) 在“公共类 Form1”行上方添加此 VB.Net 代码:
<System.Runtime.InteropServices.ComVisibleAttribute(True)> <System.Runtime.InteropServices.ComVisibleAttribute(True)>

Step 4) Add a WebBrowser control to your project步骤 4) 将 WebBrowser 控件添加到您的项目中

Step 5) Add this VB.Net code to your Form1_Load function:步骤 5) 将此 VB.Net 代码添加到您的 Form1_Load 函数中:
WebBrowser1.ObjectForScripting = Me WebBrowser1.ObjectForScripting = 我

Step 6) Add this VB.Net sub which will inject a function "CallbackGetVar" into the web page's Javascript:步骤 6) 添加此 VB.Net sub,它将向网页的 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

Step 7) Add the following VB.Net sub which the Javascript will then look for when invoked:步骤 7)添加以下 VB.Net 子程序,Javascript 将在调用时查找该子程序:

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

Step 8) Finally, to invoke the Javascript callback, add this VB.Net code when a button is pressed, or wherever you like:步骤 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

Step 9) If it surprises you that this works, you may want to read up on the Javascript "eval" function, used in Step 6, which is what makes this possible.第 9 步)如果您感到惊讶,这确实有效,您可能需要阅读第 6 步中使用的 Javascript“eval”函数,这就是使这成为可能的原因。 It will take a string and determine whether a variable exists with that name and, if so, returns the value of that variable.它将接受一个字符串并确定是否存在具有该名称的变量,如果存在,则返回该变量的值。

You can always use a "DocumentStream" or "DocumentText" property.您始终可以使用“DocumentStream”或“DocumentText”属性。 For working with HTML documents I recommend a HTML Agility Pack .为了处理 HTML 文档,我推荐使用HTML Agility Pack

我用这个:

webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })

What you want to do is use Page.RegisterStartupScript(key, script) :你想要做的是使用 Page.RegisterStartupScript(key, script) :

See here for more details: http://msdn.microsoft.com/en-us/library/aa478975.aspx有关更多详细信息,请参见此处: http : //msdn.microsoft.com/en-us/library/aa478975.aspx

What you basically do is build your javascript string, pass it to that method and give it a unique id( in case you try to register it twice on a page.)您基本上要做的是构建您的 javascript 字符串,将其传递给该方法并为其指定一个唯一的 id(以防您尝试在页面上注册两次。)

EDIT: This is what you call trigger happy.编辑:这就是你所说的触发器快乐。 Feel free to down it.随意放下它。 :) :)

If you need to inject a whole file then you can use this:如果您需要注入整个文件,则可以使用以下命令:

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

Remember to import System.IO in order to use the StreamReader .请记住导入System.IO以使用StreamReader I hope this helps.我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM