2008-09-30 71 views
70

我已經試過這樣:如何在WebBrowser控件中注入Javascript?

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?

回答

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字符串,它傳遞給方法,並給它一個唯一的ID(如果你嘗試在網頁上註冊兩次)。

編輯:這就是你所說的觸發快樂。隨意下來吧。 :)

+4

ASP.Net沒有按與在Winforms應用程序中編寫WebBrowser控件腳本無關。 – 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文件並沒有完全實現你需要的功能的託管包裝,所以你需要動用MSHTML的API來完成你想要的東西:

1)添加引用MSHTML,這將probalby在COM引用下被稱爲「Microsoft HTML Object Library」。

2)添加'使用mshtml;'到你的名字空間。

3)獲取關於你的腳本元素的IHTMLElement:

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement; 

4)調用insertAdjacentText方法,以 「afterBegin」 的第一個參數值。所有可能的值列here

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

5)現在,你就可以看到scriptEl.InnerText屬性的代碼。

H個, 理查德

+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在WebBrowser控制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窗體和WPF WebBrowser控件。

此解決方案不跨瀏覽器,因爲「execScript」僅在IE和Chrome中定義。但問題是關於微軟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)添加上方的 「公共類Form1中」 行此VB.Net代碼:
< System.Runtime.InteropServices.ComVisibleAttribute(真)>

步驟4)添加一個web瀏覽器控件到你的項目

步驟5)本VB.Net代碼添加到您的Form1_Load的功能:
WebBrowser1.ObjectForScripting =我

步驟6)添加此VB。網子將注入功能「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)如果讓你驚訝的是這個工程,遊馬我想讀一下第6步中使用的Javascript「eval」函數,這是可能的。它將接收一個字符串並確定一個變量是否以該名稱存在,如果是,則返回該變量的值。

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

希望對大家有所幫助

相關問題