Как внедрить Javascript в WebBrowser control?
-
03-07-2019 - |
Вопрос
Я уже пробовал это:
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)
Есть ли простой способ внедрить скрипт в dom?
Решение
По какой-то причине решение Ричарда не сработало с моей стороны (ошибка 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
интегрируйте в свой проект.
Другие советы
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)
Редактировать:Исправлена ошибка с регистрацией в наборе функций.
Вот самый простой способ, который я нашел после работы над этим:
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 здесь.
Кроме того, в .NET 4 это еще проще, если вы используете ключевое слово dynamic:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
Если все, что вы действительно хотите, это запустить javascript, это было бы проще всего (VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
Я предполагаю, что это не будет "внедрять" его, но оно запустит вашу функцию, если это то, что вам нужно.(На всякий случай, если вы слишком усложнили задачу.) И если вы можете понять, как внедрить javascript, поместите это в тело функции "foo" и позвольте javascript выполнить внедрение за вас.
Управляемая оболочка для HTML-документа не полностью реализует необходимую вам функциональность, поэтому вам нужно погрузиться в MSHTML API, чтобы выполнить то, что вы хотите:
1) Добавьте ссылку на MSHTML, которая, вероятно, будет называться "Библиотека объектов Microsoft HTML" в разделе КОМ ссылки.
2) Добавьте "используя mshtml;" в ваши пространства имен.
3) Получите ссылку на элемент IHTMLElement вашего скрипта:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) Вызовите метод insertAdjacentText с первым значением параметра "afterBegin".Перечислены все возможные значения здесь:
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");
5) Теперь вы сможете увидеть код в scriptEl.Свойство innerText.
Hth, Ричард
В качестве последующей меры по итогам принятый ответ, это минимальное определение 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");
}
}
}
}
это решение с использованием 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);
Я считаю, что самый простой способ внедрить 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 с ключевым словом new.Этот пример создает анонимную функцию с введенным кодом и выполняет ее (javascript реализует замыкания, и функция имеет доступ к глобальному пространству без загрязнения локальной переменной).
var jsCode="alert('hello world');";
(new Function(code))();
Конечно, вы можете отложить выполнение:
var jsCode="alert('hello world');";
var inserted=new Function(code);
.................
inserted();
Надеюсь, это поможет
Я использовал это: 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");
Я надеюсь быть полезным
Вот VB.Чистый пример, если вы пытаетесь получить значение переменной изнутри страницы, загруженной в элемент управления WebBrowser.
Шаг 1) Добавьте ссылку COM в свой проект на библиотеку объектов Microsoft HTML
Шаг 2) Затем добавьте этот VB.Net-код в вашу Form1 для импорта библиотеки mshtml:
Импортирует mshtml
Шаг 3) Добавьте этот VB.Чистый код над вашей строкой "Открытый класс Form1":
<System.Runtime.InteropServices.ComVisibleAttribute(True)>
Шаг 4) Добавьте веб-браузерный элемент управления в свой проект
Шаг 5) Добавьте этот VB.Чистый код в вашу функцию Form1_Load:
webBrowser1.ObjectForScripting = Я
Шаг 6) Добавьте этот VB.Net sub, который введет функцию "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 sub, который затем будет искать Javascript при вызове:
Public Sub Callback_GetVar(ByVal vVar As String)
Debug.Print(vVar)
End Sub
Шаг 8) Наконец, чтобы вызвать обратный вызов Javascript, добавьте этот VB.Чистый код при нажатии кнопки или где угодно:
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, которая делает это возможным.Он примет строку и определит, существует ли переменная с таким именем, и, если да, вернет значение этой переменной.
Вы всегда можете использовать свойство "DocumentStream" или "DocumentText".Для работы с HTML-документами я рекомендую HTML-пакет Гибкости.
Что вы хотите сделать, так это использовать Page.RegisterStartupScript (ключ, скрипт) :
Смотрите здесь для получения более подробной информации: http://msdn.microsoft.com/en-us/library/aa478975.aspx
Что вы в основном делаете, так это создаете свою строку javascript, передаете ее этому методу и присваиваете ему уникальный идентификатор (на случай, если вы попытаетесь зарегистрировать его дважды на странице).)
Редактировать:Это то, что вы называете триггерным счастьем.Не стесняйтесь записывать это.:)
я использую это:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
Если вам нужно ввести весь файл целиком, вы можете использовать это:
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
.Я надеюсь, что это поможет.