Как вставить Javascript в элемент управления WebBrowser?

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

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)

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
81
0
163 531
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Что вы хотите сделать, так это использовать Page.RegisterStartupScript (ключ, скрипт) :

Подробнее см. Здесь: http://msdn.microsoft.com/en-us/library/aa478975.aspx

В основном вы создаете свою строку javascript, передаете ее этому методу и присваиваете ей уникальный идентификатор (на случай, если вы попытаетесь зарегистрировать ее дважды на странице).

Обновлено: это то, что вы называете триггером счастливым. Не стесняйтесь опускать его. :)

ASP.Net не имеет особого отношения к написанию сценария элемента управления WebBrowser в приложении winforms.

jsight 30.09.2008 20:08

Я бы, наверное, недочитал так же и дал такой же неверный ответ

Grank 30.09.2008 20:14

Вы всегда можете использовать свойство «DocumentStream» или «DocumentText». Для работы с HTML-документами я рекомендую Пакет гибкости HTML.

Хороший совет ... Я уверен, что lib когда-нибудь пригодится.

jsight 30.09.2008 23:40

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

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, Ричард

Приятно ... это вместе с советами Корчева отлично работает. Хотел бы я установить два принятых решения для этого. :)

jsight 30.09.2008 23:40
Ответ принят как подходящий

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

Круто, я думаю, что использование IHTMLScriptElement в любом случае делает намерение кода более очевидным. Мне действительно интересно, почему у вас есть исключение, но иногда c'est la vie с COM-взаимодействием.

ZeroBugBounce 01.10.2008 00:02

А как насчет добавления ссылки на локальный файл js? См. stackoverflow.com/questions/4029602/…

IAmAN00B 27.10.2010 18:03

Пожалуйста, помогите мне с этим. Как ты это сделал. Я хочу внедрить JS на свою страницу в реальном времени через приложение C++. Как мне это сделать.

Johnydep 03.06.2011 22:09

применимо ли это также для ввода файла jquery?

gumuruh 12.07.2020 13:07

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

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

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

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

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

Зачем кому-то для этого нужна динамика? Если вы пытаетесь сэкономить на вводе, у нас есть вывод типа, начиная с C# 3.0, поэтому var будет приемлемым. Нет необходимости запускать DLR.

alimbada 11.08.2010 15:11

В этом суть ключевого слова dynamic: COM-взаимодействие. На самом деле здесь нет вывода типа, у вас есть документация. Поскольку IHTMLElement2 не может быть назначен, например, из IHtmlElement, а во время выполнения у вас есть просто прокси-объект COM. Вам просто нужно знать, какие интерфейсы и во что преобразовывать. Ключевое слово dynamic поможет вам избавиться от лишней ерунды. Вы знаете, что метод существует, зачем использовать его в каком-то интерфейсе? Он не совсем «вызывает DLR», он просто генерирует код, который знает, как вызывать метод для COM-объектов (в данном случае).

justin.m.chase 31.12.2010 07:56

@ justin.m.chase ты спас мне жизнь.

Khizar Iqbal 06.11.2017 20:48

это решение с использованием 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);

Поскольку это ресурс сообщества, его ответ по-прежнему будет полезен другим (например, мне). +1 для эквивалента mshtml, избавил меня от вопроса.

Kyeotic 12.09.2011 18:47

Для тех, кто найдет это, удалите «класс» из последней строки, следует читать ((HTMLHeadElement)head).appendChild((IHTMLDOMNode)scriptObje‌​ct);, иначе вы получите ошибки.

Kyeotic 12.09.2011 19:29

Могут ли админы продвигать этот ответ? Те, что выше, в действительности неверны. Этот ответ пришел поздно, но на самом деле это самый правильный ответ.

justin.m.chase 22.12.2012 21:32

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)

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

Мне понравилось это решение, потому что оно не полагается на (хотя и полезную!) Сборку IHTMLSCriptElement.

Micah Smith 24.09.2011 02:19

@jsight Это должен быть принятый ответ. Это то же самое, что и текущий ответ, но проще и без зависимости IHTMLSCriptElement.

BlueRaja - Danny Pflughoeft 12.12.2013 14:29

Я считаю, что самый простой метод внедрения Javascript в HTML-документ WebBrowser Control из C# - это вызвать метод execScript с кодом, который будет введен в качестве аргумента.

В этом примере код 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();

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

Вот пример VB.Net, если вы пытаетесь получить значение переменной из страницы, загруженной в элемент управления WebBrowser.

Шаг 1) Добавьте ссылку на COM в свой проект в библиотеку объектов Microsoft HTML.

Шаг 2) Затем добавьте этот код VB.Net в форму Form1, чтобы импортировать библиотеку mshtml:
Импорт mshtml

Шаг 3) Добавьте этот код VB.Net над строкой «Public Class Form1»:
<System.Runtime.InteropServices.ComVisibleAttribute (True)>

Шаг 4) Добавьте элемент управления WebBrowser в свой проект

Шаг 5) Добавьте этот код VB.Net в свою функцию Form1_Load:
WebBrowser1.ObjectForScripting = Я

Шаг 6) Добавьте эту подпрограмму VB.Net, которая будет вставлять функцию CallbackGetVar в Javascript веб-страницы:

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

Шаг 7) Добавьте следующую подпрограмму VB.Net, которую Javascript будет искать при вызове:

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

Шаг 8) Наконец, чтобы вызвать обратный вызов Javascript, добавьте этот код VB.Net при нажатии кнопки или где угодно:

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

Шаг 9) Если вас удивит, что это работает, вы можете прочитать о функции Javascript "eval", использованной на шаге 6, которая и делает это возможным. Он берет строку и определяет, существует ли переменная с таким именем, и, если да, возвращает значение этой переменной.

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

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 здесь.

Как продолжение принятый ответ, это минимальное определение 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");
            }
        }
    }
}

Если вам нужно ввести целый файл, вы можете использовать это:

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

Не забудьте импортировать System.IO, чтобы использовать StreamReader. Надеюсь, это поможет.

Я знаю, что на этот вопрос ответили за 3 дня до года назад, но сможете ли вы использовать это, чтобы поместить файл в раздел input type = "file"?

Chris Hobbs 05.11.2015 20:12

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

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

я использую это:

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

Другие вопросы по теме