Pergunta

Eu tentei o seguinte:

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 Ambos os erros:

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 uma maneira fácil de injetar um script no DOM?

Foi útil?

Solução

Por alguma razão, a solução de Richard não funcionou do meu lado (o insertadjacenttext falhou com uma exceção). No entanto, isso 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 resposta explica como obter o IHTMLScriptElement Interface em seu projeto.

Outras dicas

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

(Testado no aplicativo .NET 4 / Windows Forms)

Editar: Problema de caso fixo no conjunto de funções.

Aqui está a maneira mais fácil que eu encontrei depois de trabalhar nisso:

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

Qual função global de javascript eval(str) Faz é parses e executa o que está escrito em STR. Verificar W3Schools Ref aqui.

Além disso, no .NET 4, isso é ainda mais fácil se você usar a palavra -chave dinâmica:

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

Se tudo o que você realmente quer é executar o JavaScript, isso seria mais fácil (VB .NET):

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

Eu acho que isso não o "injetaria", mas vai executar sua função, se é isso que você procura. (Caso você tenha complicado demais o problema.) E se você puder descobrir como injetar em JavaScript, coloque-o no corpo da função "foo" e deixe o JavaScript fazer a injeção para você.

O invólucro gerenciado para o documento HTML não implementa completamente a funcionalidade necessária, então você precisa mergulhar na API MSHTML para realizar o que deseja:

1) Adicione uma referência ao mshtml, que provavelmente será chamado de "Microsoft HTML Object Library" em Com referências.

2) Adicione 'usando mshtml;' para seus namespaces.

3) Obtenha uma referência ao seu elemento de script IHTMLELEMENT:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4) Ligue para o método InsertadjacentText, com o primeiro valor de parâmetro de "Afterbegin". Todos os valores possíveis estão listados aqui:

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

5) Agora você poderá ver o código na propriedade Scriptel.innerText.

HTH, Richard

Como acompanhamento do resposta aceita, esta é uma definição mínima do IHTMLScriptElement interface que não precisa incluir bibliotecas de tipos adicionais:

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

Portanto, um código completo dentro de uma classe derivada de controle da web -Browser seria:

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

Esta é uma solução 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);

Acredito que o método mais simples de injetar JavaScript em um documento HTML de controle Webbrowser de C# é invocar o método "ExecStrip" com o código a ser injetado como argumento.

Neste exemplo, o código JavaScript é injetado e executado no Global Scope:

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

Se você deseja atrasar a execução, injete funções e ligue para depois de:

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

Isso é válido para os formulários do Windows e controles WPF WebBrowser.

Esta solução não é navegador transversal porque "ExecScript" é definido apenas no IE e Chrome. Mas a questão é sobre os controles do Microsoft WebBrowser e o IE é o único suportado.

Para um método de navegador cruzado válido para injetar código JavaScript, crie um objeto de função com a nova palavra -chave. Este exemplo cria uma função anônima com código injetado e o executa (o JavaScript implementa o fechamento e a função tem acesso ao espaço global sem poluição da variável local).

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

Claro, você pode atrasar a execução:

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

Espero que ajude

Eu usei isso: D

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

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

Então você pode executar e obter o resultado com:

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

Espero ser útil

Aqui está um exemplo vb.net se você estiver tentando recuperar o valor de uma variável em uma página carregada em um controle WebBrowser.

Etapa 1) Adicione uma referência COM em seu projeto à Microsoft HTML Object Library

Etapa 2) Em seguida, adicione este código VB.NET ao seu Form1 para importar a biblioteca MSHTML:
Importa mshtml

Etapa 3) Adicione este código VB.NET acima da sua linha "Public Class Form1":
u003CSystem.Runtime.InteropServices.ComVisibleAttribute(True)>

Etapa 4) Adicione um controle WebBrowser ao seu projeto

Etapa 5) Adicione este código vb.net à sua função form1_load:
Webbrowser1.ObjectForScripting = eu

Etapa 6) Adicione este sub VB.NET que injetará uma função "chamada de chamada" no JavaScript da página da 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

Etapa 7) Adicione o seguinte Sub VB.NET que o JavaScript procurará quando invocar:

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

Etapa 8) Finalmente, para invocar o retorno de chamada do JavaScript, adicione este código VB.NET quando um botão for pressionado ou onde quiser:

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

Etapa 9) Se isso o surpreender que isso funcione, convém ler a função JavaScript "Eval", usada na Etapa 6, que é o que torna isso possível. Ele levará uma string e determinará se existe uma variável com esse nome e, nesse caso, retorna o valor dessa variável.

Você sempre pode usar uma propriedade "DocumentStream" ou "DocumentText". Para trabalhar com documentos HTML, recomendo um HTML Agility Pack.

O que você deseja fazer é usar a página.RegisterStartupScript (chave, script):

Veja aqui para mais detalhes: http://msdn.microsoft.com/en-us/library/aa478975.aspx

O que você basicamente faz é criar sua string javascript, passar para esse método e dar um ID exclusivo (caso você tente registrá -lo duas vezes em uma página.)

EDIT: É isso que você chama de gatilho feliz. Sinta -se à vontade para diminuir. :)

Eu uso isso:

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

Se você precisar injetar um arquivo inteiro, poderá usar isso:

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

Lembre -se de importar System.IO Para usar o StreamReader. Eu espero que isso ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top