我试过这个:
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吗?
答案 0 :(得分:97)
由于某些原因,理查德的解决方案在我的结尾不起作用(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");
This answer解释了如何将IHTMLScriptElement
界面纳入您的项目。
答案 1 :(得分:45)
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中测试)
编辑:修复了功能集中的案例问题。
答案 2 :(得分:27)
这是我在完成这项工作后找到的最简单方法:
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 here。
答案 3 :(得分:21)
此外,在.NET 4中,如果使用动态关键字,则更容易:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
答案 4 :(得分:17)
如果您真正想要的是运行javascript,这将是最简单的(VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
我想这不会“注入”但它会运行你的功能,如果这就是你所追求的。 (以防万一你的问题过于复杂。)如果你能弄清楚如何在javascript中注入,那就把它放到函数“foo”的主体中,然后让javascript为你做注入。
答案 5 :(得分:10)
HTML文档的托管包装器并不能完全实现您需要的功能,因此您需要深入了解MSHTML API以实现您的目标:
1)添加对MSHTML的引用,它将在 COM 引用下被称为“Microsoft HTML Object Library”。
2)添加'using mshtml;'到您的名称空间。
3)获取对脚本元素的IHTMLElement的引用:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4)调用insertAdjacentText方法,第一个参数值为“afterBegin”。列出了所有可能的值here:
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");
5)现在,您将能够看到scriptEl.InnerText属性中的代码。
H个, 理查德
答案 6 :(得分: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);
答案 7 :(得分:7)
我认为从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();
希望有所帮助
答案 8 :(得分:7)
作为accepted answer的后续内容,这是IHTMLScriptElement
interface的最小定义,不需要包含其他类型库:
[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");
}
}
}
}
答案 9 :(得分:2)
如果您尝试从WebBrowser控件中加载的页面中检索变量的值,这是一个VB.Net示例。
步骤1)将项目中的COM引用添加到Microsoft HTML Object Library
步骤2)接下来,将此VB.Net代码添加到Form1以导入mshtml库:
导入mshtml
步骤3)将此VB.Net代码添加到“Public Class Form1”行上方:
< System.Runtime.InteropServices.ComVisibleAttribute(真)>
步骤4)将WebBrowser控件添加到项目中
步骤5)将此VB.Net代码添加到Form1_Load函数中:
WebBrowser1.ObjectForScripting = Me
步骤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 sub,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”函数,这就是使其成为可能的原因。它将采用一个字符串并确定变量是否与该名称一起存在,如果存在,则返回该变量的值。
答案 10 :(得分: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");
我希望能提供帮助
答案 11 :(得分:1)
您始终可以使用“DocumentStream”或“DocumentText”属性。 要使用HTML文档,我建议使用HTML Agility Pack。
答案 12 :(得分:0)
您要做的是使用Page.RegisterStartupScript(键,脚本) :
请点击此处了解详情:http://msdn.microsoft.com/en-us/library/aa478975.aspx
你基本上做的是构建你的javascript字符串,将它传递给该方法并给它一个唯一的id(如果你试图在页面上注册两次。)
编辑:这就是你所谓的触发器快乐。随意放下它。 :)答案 13 :(得分: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
。我希望这会有所帮助。
答案 14 :(得分:0)
我用这个:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })