J'ai essayé ceci:
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 et scriptEl.InnerText donnent tous deux des erreurs:
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)
Existe-t-il un moyen facile d’injecter un script dans le dom?
Pour une raison quelconque, la solution de Richard n'a pas fonctionné de mon côté (insertAdjacentText a échoué avec une exception). Cela semble cependant fonctionner:
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");
Cette réponse explique comment insérer l'interface IHTMLScriptElement
dans votre projet.
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");
(testé dans .NET 4/Windows Forms App)
Modifier: problème de casse résolu dans le jeu de fonctions.
Voici le moyen le plus simple que j'ai trouvé après avoir travaillé sur ceci:
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 });
Ce que la fonction JavaScript globale eval(str)
fait, c'est d'analyser et d'exécuter tout ce qui est écrit dans str. Vérifiez réf. W3schools ici .
En outre, dans .NET 4, cela est encore plus facile si vous utilisez le mot-clé dynamic:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
Si tout ce que vous voulez, c'est exécuter du javascript, ce serait plus simple (VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
J'imagine que cela ne "l'injecterait" pas, mais que votre fonction serait exécutée, si c'est ce que vous recherchez. (Juste au cas où vous auriez trop compliqué le problème.) Et si vous pouvez comprendre comment injecter du javascript, mettez cela dans le corps de la fonction "foo" et laissez le javascript faire l'injection à votre place.
Le wrapper géré pour le document HTML n'implémente pas complètement la fonctionnalité dont vous avez besoin, vous devez donc plonger dans l'API MSHTML pour accomplir ce que vous voulez:
1) Ajoutez une référence à MSHTML, qui sera probablement appelée "Bibliothèque d'objets Microsoft HTML" sous [~ # ~] com [~ # ~] références .
2) Ajouter 'using mshtml;' à vos espaces de noms.
3) Obtenez une référence au IHTMLElement de votre élément de script:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) Appelez la méthode insertAdjacentText, avec la première valeur de paramètre "afterBegin". Toutes les valeurs possibles sont listées ici :
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");
5) Vous pourrez maintenant voir le code dans la propriété scriptEl.InnerText.
Hth, Richard
Pour faire suite à réponse acceptée , il s'agit d'une définition minimale de l'interface IHTMLScriptElement
qui ne nécessite pas l'inclusion de bibliothèques de types supplémentaires:
[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; }
}
Ainsi, un code complet dans une classe dérivée de contrôle WebBrowser ressemblerait à ceci:
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");
}
}
}
}
c'est une solution utilisant 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);
Je pense que la méthode la plus simple pour injecter du code Javascript dans un document HTML de WebBrowser Control à partir de c # consiste à appeler la méthode "execStrip" avec le code à injecter en tant qu'argument.
Dans cet exemple, le code javascript est injecté et exécuté au niveau global:
var jsCode="alert('hello world from injected code');";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
Si vous souhaitez retarder l'exécution, injectez des fonctions et appelez-les après:
var jsCode="function greet(msg){alert(msg);};";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
...............
WebBrowser.Document.InvokeScript("greet",new object[] {"hello world"});
Ceci est valable pour les contrôles Windows Forms et WPF WebBrowser.
Cette solution n’est pas compatible avec plusieurs navigateurs, car "execScript" est défini uniquement dans IE et Chrome. La question concerne toutefois les contrôles Microsoft WebBrowser et IE est le seul prise en charge.
Pour une méthode inter-navigateurs valide permettant d'injecter du code JavaScript, créez un objet Function avec le nouveau mot-clé. Cet exemple crée une fonction anonyme avec du code injecté et l'exécute (javascript implémente des fermetures et la fonction a accès à un espace global sans pollution par des variables locales).
var jsCode="alert('hello world');";
(new Function(code))();
Bien sûr, vous pouvez retarder l'exécution:
var jsCode="alert('hello world');";
var inserted=new Function(code);
.................
inserted();
J'espère que ça aide
J'ai utilisé ceci: D
HtmlElement script = this.WebNavegador.Document.CreateElement("SCRIPT");
script.SetAttribute("TEXT", "function GetNameFromBrowser() {" +
"return 'My name is David';" +
"}");
this.WebNavegador.Document.Body.AppendChild(script);
Ensuite, vous pouvez exécuter et obtenir le résultat avec:
string myNameIs = (string)this.WebNavegador.Document.InvokeScript("GetNameFromBrowser");
J'espère être utile
Voici un exemple VB.Net si vous essayez d'extraire la valeur d'une variable à partir d'une page chargée dans un contrôle WebBrowser.
Étape 1) Ajouter une référence COM dans votre projet à la bibliothèque d'objets Microsoft HTML
Étape 2) Ensuite, ajoutez ce code VB.Net à votre Form1 pour importer la bibliothèque mshtml:
Importations mshtml
Étape 3) Ajoutez ce code VB.Net au-dessus de votre ligne "Public Class Form1":
<System.Runtime.InteropServices.ComVisibleAttribute (True)>
Étape 4) Ajouter un contrôle WebBrowser à votre projet
Étape 5) Ajoutez ce code VB.Net à votre fonction Form1 Load:
WebBrowser1.ObjectForScripting = Me
Étape 6) Ajoutez ce sous-répertoire VB.Net qui injectera une fonction "CallbackGetVar" dans le code Javascript de la page 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
Étape 7) Ajoutez le sous-fichier VB.Net suivant que le Javascript recherchera ensuite lorsqu’il est appelé:
Public Sub Callback_GetVar(ByVal vVar As String)
Debug.Print(vVar)
End Sub
Étape 8) Enfin, pour invoquer le rappel Javascript, ajoutez ce code VB.Net lorsque vous appuyez sur un bouton ou à l'endroit souhaité:
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
Étape 9) Si cela vous surprend, vous voudrez peut-être lire la fonction javascript "eval", utilisée à l'étape 6, qui rend tout cela possible. Il faudra une chaîne pour déterminer si une variable existe avec ce nom et, si tel est le cas, renvoie la valeur de cette variable.
Vous pouvez toujours utiliser une propriété "DocumentStream" ou "DocumentText". Pour travailler avec des documents HTML, je recommande un HTML Agility Pack .
j'utilise ceci:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
Si vous devez injecter un fichier entier, vous pouvez utiliser ceci:
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
N'oubliez pas d'importer System.IO
pour utiliser le StreamReader
. J'espère que ça aide.
Ce que vous voulez faire est d'utiliser Page.RegisterStartupScript (clé, script):
Voir ici pour plus de détails: http://msdn.Microsoft.com/en-us/library/aa478975.aspx
En gros, vous construisez votre chaîne javascript, transmettez-la à cette méthode et attribuez-lui un identifiant unique (si vous essayez de l'enregistrer deux fois sur une page).
EDIT: C'est ce que vous appelez le déclencheur heureux. N'hésitez pas à le descendre. :)