c# - enable - ihtmlscriptelement
Cómo inyectar Javascript en el control WebBrowser? (15)
Además, en .NET 4, esto es aún más fácil si usa la palabra clave dinámica:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
He intentado esto:
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 y scriptEl.InnerText ambos dan errores:
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)
¿Hay alguna manera fácil de insertar un script en el dom?
Aquí hay un ejemplo de VB.Net si está tratando de recuperar el valor de una variable desde una página cargada en un control WebBrowser.
Paso 1) Agregue una referencia COM en su proyecto a la Biblioteca de objetos HTML de Microsoft
Paso 2) A continuación, agregue este código VB.Net a su Form1 para importar la biblioteca mshtml:
Importa mshtml
Paso 3) Agregue este código de VB.Net sobre su línea "Form1 de Clase Pública":
<System.Runtime.InteropServices.ComVisibleAttribute (True)>
Paso 4) Agregue un control WebBrowser a su proyecto
Paso 5) Agregue este código VB.Net a su función Form1_Load:
WebBrowser1.ObjectForScripting = Me
Paso 6) Agregue este sub de VB.Net que inyectará una función "CallbackGetVar" en el Javascript de la página web:
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
Paso 7) Agregue el siguiente subcarpe de VB.Net que el Javascript buscará cuando se invoque:
Public Sub Callback_GetVar(ByVal vVar As String)
Debug.Print(vVar)
End Sub
Paso 8) Finalmente, para invocar la devolución de llamada de Javascript, agregue este código de VB.Net cuando se presione un botón, o donde desee:
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
Paso 9) Si le sorprende que esto funcione, le recomendamos que lea la función "eval" de Javascript, utilizada en el Paso 6, que es lo que hace esto posible. Tomará una cadena y determinará si existe una variable con ese nombre y, de ser así, devolverá el valor de esa variable.
Como seguimiento de la respuesta aceptada , esta es una definición mínima de la interfaz IHTMLScriptElement
que no requiere incluir bibliotecas de tipos adicionales:
[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; }
}
Así que un código completo dentro de una clase derivada de control WebBrowser se vería así:
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");
}
}
}
}
Creo que el método más simple para inyectar Javascript en un documento HTML Control WebBrowser desde c # es invocar el método "execStrip" con el código que se inyectará como argumento.
En este ejemplo, el código javascript se inyecta y se ejecuta en el ámbito global:
var jsCode="alert(''hello world from injected code'');";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
Si desea retrasar la ejecución, inyecte funciones y llámelas después de:
var jsCode="function greet(msg){alert(msg);};";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
...............
WebBrowser.Document.InvokeScript("greet",new object[] {"hello world"});
Esto es válido para los controles de Windows Forms y WPF WebBrowser.
Esta solución no es un navegador cruzado porque "execScript" está definido solo en IE y Chrome. Pero la pregunta es acerca de los controles de Microsoft WebBrowser y IE es el único compatible.
Para un método de navegador cruzado válido para inyectar código JavaScript, cree un objeto Function con la nueva Palabra clave. Este ejemplo crea una función anónima con código inyectado y lo ejecuta (javascript implementa cierres y la función tiene acceso al espacio global sin contaminación variable local).
var jsCode="alert(''hello world'');";
(new Function(code))();
Por supuesto, puede retrasar la ejecución:
var jsCode="alert(''hello world'');";
var inserted=new Function(code);
.................
inserted();
Espero eso ayude
El contenedor administrado para el documento HTML no implementa por completo la funcionalidad que necesita, por lo que necesita profundizar en la API de MSHTML para lograr lo que desea:
1) Agregue una referencia a MSHTML, que probablemente se denominará "Biblioteca de objetos HTML de Microsoft" bajo referencias COM .
2) Agregue ''usando mshtml;'' a tus espacios de nombres
3) Obtenga una referencia al elemento IHTMLElement de su elemento de script:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) Llame al método insertAdjacentText, con el primer valor de parámetro de "afterBegin". Todos los valores posibles se enumeran here :
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert(''hello'') }");
5) Ahora podrá ver el código en la propiedad scriptEl.InnerText.
Hth, Richard
Esta es la forma más fácil que encontré después de trabajar en esto:
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 });
Lo que hace la función global de JavaScript eval(str)
es analizar y ejecutar lo que está escrito en str. Consulte la referencia de w3schools aquí .
Lo que quiere hacer es usar Page.RegisterStartupScript (clave, script):
Consulte aquí para obtener más detalles: http://msdn.microsoft.com/en-us/library/aa478975.aspx
Lo que básicamente hace es crear su cadena de javascript, pasarla a ese método y darle una identificación única (en caso de que intente registrarla dos veces en una página).
EDITAR: Esto es lo que llamas feliz gatillo. Siéntete libre de derribarlo. :)
Por alguna razón, la solución de Richard no funcionó en mi extremo (insertAdjacentText falló con una excepción). Sin embargo, esto parece funcionar:
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");
Esta respuesta explica cómo obtener la interfaz IHTMLScriptElement
en su proyecto.
Si necesita inyectar un archivo completo, puede usar esto:
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''
Recuerde importar System.IO para usar StreamReader. Espero que te ayude
Si todo lo que realmente quieres es ejecutar javascript, esto sería más fácil (VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert(''hello'');}foo();")
Supongo que esto no lo "inyectará", pero ejecutará tu función, si eso es lo que buscas. (En caso de que haya complicado demasiado el problema). Y si puede averiguar cómo inyectar en javascript, ponga eso en el cuerpo de la función "foo" y deje que javascript haga la inyección por usted.
Siempre puede usar una propiedad "DocumentStream" o "DocumentText". Para trabajar con documentos HTML, recomiendo un HTML Agility Pack .
Usé esto: D
HtmlElement script = this.WebNavegador.Document.CreateElement("SCRIPT");
script.SetAttribute("TEXT", "function GetNameFromBrowser() {" +
"return ''My name is David'';" +
"}");
this.WebNavegador.Document.Body.AppendChild(script);
Luego puede ejecutar y obtener el resultado con:
string myNameIs = (string)this.WebNavegador.Document.InvokeScript("GetNameFromBrowser");
Espero ser útil
esta es una solución usando 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);
yo uso esto:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
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");
(probado en la aplicación .NET 4 / Windows Forms)
Editar: problema de caso fijo en el conjunto de funciones.