Come iniettare Javascript nel controllo WebBrowser?

Ho provato questo:

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 e scriptEl.InnerText forniscono entrambi errori:

 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) 

C’è un modo semplice per iniettare una sceneggiatura nella dom?

Per qualche motivo la soluzione di Richard non ha funzionato sulla mia parte (insertAdjacentText fallito con un’eccezione). Questo tuttavia sembra funzionare:

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

Questa risposta spiega come ottenere l’interfaccia IHTMLScriptElement nel progetto.

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

(testato in .NET 4 / Windows Forms App)

Modifica: problema risolto del caso nel set di funzioni.

Ecco il modo più semplice che ho trovato dopo aver lavorato su questo:

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

La funzione JavaScript globale eval(str) esegue l’analisi e esegue ciò che è scritto in str. Controlla ref w3schools qui .

Inoltre, in .NET 4 questo è ancora più semplice se si utilizza la parola chiave dynamic:

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

Se tutto ciò che vuoi veramente è eseguire javascript, questo sarebbe più semplice (VB .Net):

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

Immagino che questo non “lo inietti” ma eseguirà la tua funzione, se è quello che cerchi. (Nel caso abbiate complicato troppo il problema.) E se riuscite a capire come iniettare in javascript, inseritelo nel corpo della funzione “foo” e lasciate che il javascript faccia l’iniezione per voi.

Il wrapper gestito per il documento HTML non implementa completamente la funzionalità di cui hai bisogno, quindi devi immergerti nell’API MSHTML per ottenere ciò che desideri:

1) Aggiungere un riferimento a MSHTML, che verrà probabilmente chiamato “Microsoft HTML Object Library” sotto i riferimenti COM .

2) Aggiungi “usando mshtml;” ai tuoi spazi dei nomi.

3) Ottieni un riferimento al tuo IHTMLElement dell’elemento di script:

 IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement; 

4) Chiamare il metodo insertAdjacentText, con il primo valore di parametro “afterBegin”. Tutti i valori possibili sono elencati qui :

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

5) Ora sarai in grado di vedere il codice nella proprietà scriptEl.InnerText.

Hth, Richard

questa è una soluzione che usa 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); 

Credo che il metodo più semplice per iniettare Javascript in un documento HTML di controllo WebBrowser da C # sia quello di richiamare il metodo “execStrip” con il codice da iniettare come argomento.

In questo esempio il codice javascript viene iniettato ed eseguito nell’ambito globale:

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

Se vuoi ritardare l’esecuzione, inserisci le funzioni e chiamale dopo:

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

Questo è valido per i controlli Windows Form e WPF WebBrowser.

Questa soluzione non è cross browser perché “execScript” è definito solo in IE e Chrome. Ma la domanda riguarda i controlli di Microsoft WebBrowser e IE è l’unico supportato.

Per un valido metodo cross browser per iniettare il codice javascript, creare un object Function con la nuova parola chiave. Questo esempio crea una funzione anonima con codice iniettato e la esegue (javascript implementa le chiusure e la funzione ha accesso allo spazio globale senza inquinamento variabile locale).

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

Certo, puoi ritardare l’esecuzione:

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

Spero che sia d’aiuto

Come follow-up della risposta accettata , questa è una definizione minima dell’interfaccia IHTMLScriptElement che non richiede l’inclusione di librerie di tipi aggiuntive:

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

Quindi un codice completo all’interno di una class derivata dal controllo WebBrowser sarebbe simile a:

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

Ho usato questo: D

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

Quindi puoi eseguire e ottenere il risultato con:

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

Spero di essere utile

È sempre ansible utilizzare una proprietà “DocumentStream” o “DocumentText”. Per lavorare con documenti HTML, consiglio un Agility Pack HTML .

Ecco un esempio di VB.Net se si sta tentando di recuperare il valore di una variabile da una pagina caricata in un controllo WebBrowser.

Passaggio 1) Aggiungere un riferimento COM nel progetto alla libreria di oggetti HTML di Microsoft

Passaggio 2) Quindi, aggiungere questo codice VB.Net al proprio Form1 per importare la libreria mshtml:
Importa mshtml

Passaggio 3) Aggiungere questo codice VB.Net sopra la riga “Public Class Form1”:

Passaggio 4) Aggiungere un controllo WebBrowser al progetto

Passaggio 5) Aggiungere questo codice VB.Net alla funzione Form1_Load:
WebBrowser1.ObjectForScripting = Me

Passaggio 6) Aggiungi questo sub VB.Net che inietterà una funzione “CallbackGetVar” nel Javascript della pagina 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 

Passaggio 7) Aggiungi il seguente sub VB.Net che il Javascript cercherà quando richiamato:

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

Passaggio 8) Infine, per richiamare la richiamata JavaScript, aggiungere questo codice VB.Net quando si preme un pulsante o ovunque si desideri:

  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 

Passo 9) Se ti sorprende che questo funzioni, potresti voler leggere la funzione Javascript “eval”, utilizzata nel Passaggio 6, che è ciò che rende questo ansible. Prenderà una stringa e determinerà se esiste una variabile con quel nome e, in tal caso, restituirà il valore di quella variabile.

Quello che vuoi fare è usare Page.RegisterStartupScript (chiave, script):

Vedi qui per maggiori dettagli: http://msdn.microsoft.com/en-us/library/aa478975.aspx

Quello che fondamentalmente fai è build la tua stringa javascript, passarla a quel metodo e dargli un ID univoco (nel caso in cui tenti di registrarlo due volte su una pagina).

EDIT: Questo è ciò che chiami trigger felice. Sentiti libero di abbatterlo. 🙂

Se hai bisogno di iniettare un intero file, puoi usare questo:

 With Browser.Document' 'Dim Head As HtmlElement = .GetElementsByTagName("head")(0)' 'Dim Script As HtmlElement = .CreateElement("script")' 'Dim Streamer As New StreamReader()' 'Using Streamer' 'Script.SetAttribute("text", Streamer.ReadToEnd())' 'End Using' 'Head.AppendChild(Script)' '.InvokeScript()' 'End With' 

Ricordarsi di importare System.IO per utilizzare lo StreamReader. Spero sia di aiuto

io uso questo:

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