Как внедрить Javascript в элемент управления WebBrowser? - PullRequest
78 голосов
/ 30 сентября 2008

Я пробовал это:

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)

Есть ли простой способ ввести скрипт в домен?

Ответы [ 15 ]

97 голосов
/ 30 сентября 2008

По какой-то причине решение Ричарда не сработало на моем конце (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");

Этот ответ объясняет, как получить интерфейс IHTMLScriptElement в ваш проект.

45 голосов
/ 03 июня 2011
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)

Редактировать: Исправлена ​​проблема с регистром в наборе функций.

27 голосов
/ 31 декабря 2011

Вот самый простой способ, который я нашел после работы над этим:

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 .

21 голосов
/ 17 июня 2010

Кроме того, в .NET 4 это еще проще, если вы используете динамическое ключевое слово:

dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
17 голосов
/ 15 февраля 2010

Если все, что вам действительно нужно, это запустить javascript, это будет проще всего (VB .Net):

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

Полагаю, что это не "внедрит" это, но запустит вашу функцию, если вы к этому стремитесь. (На всякий случай, если вы слишком усложнили проблему.) И если вы можете понять, как внедрить в javascript, поместите это в тело функции "foo" и позвольте javascript выполнить за вас.

10 голосов
/ 30 сентября 2008

Управляемая оболочка для документа HTML не полностью реализует необходимую вам функциональность, поэтому вам нужно окунуться в API MSHTML, чтобы выполнить то, что вы хотите:

1) Добавьте ссылку на MSHTML, которая, вероятно, будет называться «Библиотека объектов Microsoft HTML» в разделе COM ссылки.

2) Добавить 'using mshtml;' в ваши пространства имен.

3) Получить ссылку на элемент IHTMLElement элемента скрипта:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4) Вызвать метод insertAdjacentText со значением первого параметра «afterBegin». Все возможные значения перечислены здесь :

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

5) Теперь вы сможете увидеть код в свойстве scriptEl.InnerText.

Hth, Ричард

7 голосов
/ 14 апреля 2012

В качестве продолжения принятого ответа это минимальное определение IHTMLScriptElement интерфейса , которое не требует включения дополнительных библиотек типов:

[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");
            }
        }
    }
}
7 голосов
/ 18 октября 2011

Я считаю, что самый простой способ внедрить Javascript в HTML-документ WebBrowser Control из c # - это вызвать метод "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 Forms и 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();

Надеюсь, это поможет

7 голосов
/ 18 августа 2010

это решение с использованием 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);
2 голосов
/ 19 июля 2016

Я использовал это: 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");

Я надеюсь быть полезным

...