2008-09-30 3 views
70

Я попытался это:Как добавить 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) 

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

ответ

89

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

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

+1

Прохладный, я думаю, что использование IHTMLScriptElement делает код более очевидным в любом случае. Я действительно удивляюсь, почему у вас есть исключение, но иногда встречаюсь с COM-взаимодействием. – ZeroBugBounce 2008-09-30 20:02:53

0

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

Смотрите здесь для более подробной информации: http://msdn.microsoft.com/en-us/library/aa478975.aspx

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

EDIT: Это то, что вы называете триггером счастливым. Не стесняйтесь. :)

+4

ASP.Net Безразлично 't имеет отношение к написанию элемента управления WebBrowser в приложении winforms. – jsight 2008-09-30 16:08:59

+0

Я оставлю это здесь за наказание, которого я заслуживаю;) – mattlant 2008-09-30 16:10:10

+0

Возможно, я бы так же прочитал то же самое и дал тот же неверный ответ – Grank 2008-09-30 16:14:46

1

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

+0

Хороший совет ... Я уверен, что lib пригодится в какой-то момент. – jsight 2008-09-30 19:40:59

9

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

1) Добавить ссылку на MSHTML, который будет probalby можно назвать «Microsoft HTML Object Library» под заголовком COM ссылок.

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

3) Получить ссылку на IHTMLElement вашего сценария элемента:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement; 

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

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

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

Hth, Ричард

+1

Ницца ... это вместе с советами, предоставленными korchev, отлично работает. Мне жаль, что я не смогу установить два принятых решения. :) – jsight 2008-09-30 19:40:11

17

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

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

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

21

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

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

это решение, использующее 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); 
40
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)

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

7

Я считаю, что самый простой способ для ввода Javascript в HTML-документе управления веб-браузером из 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(); 

Надеется, что это помогает

1

Вот пример 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 = Me

Шаг 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, что и делает это возможным. Он примет строку и определит, существует ли переменная с этим именем и, если это так, возвращает значение этой переменной.

23

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

string jCode = "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[] { jCode }); 

Что глобальная функция JavaScript eval(str) делает это разбирает и выполняет все, что написано на ул. Проверить w3schools ref here.

7

В качестве последующей деятельности в связи с accepted answer, это минимальное определение IHTMLScriptElement interface, которое не требует, чтобы включать дополнительные библиотеки типов:

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

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

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. Я надеюсь, что это поможет вам

2

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

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

Смежные вопросы