WebBrowser コントロールに Javascript を挿入するにはどうすればよいですか?
-
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 に注入する簡単な方法はありますか?
解決
何らかの理由で、Richardのソリューションは私の側では機能しませんでした(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 ref here を確認してください。
また、.NET 4では、動的キーワードを使用するとこれはさらに簡単になります。
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();")
これは<!> quot; inject <!> quot;ではないと思います。それがあなたの目的であれば、それはあなたの関数を実行します。 (問題を複雑にしすぎた場合に備えてください。)そして、javascriptの注入方法を理解できる場合は、それを関数<!> quot; foo <!> quotの本文に入れます。 JavaScriptがインジェクションを行うようにします。
HTML ドキュメントのマネージド ラッパーは必要な機能を完全には実装していないため、必要な機能を実現するには MSHTML API を使用する必要があります。
1) MSHTML への参照を追加します。これはおそらく「Microsoft HTML Object Library」と呼ばれます。 COM 参考文献。
2)「MSHTMLを使用して」を追加します。あなたの名前空間に。
3) スクリプト要素の IHTMLElement への参照を取得します。
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) 最初のパラメータ値「afterBegin」を指定して、insertAdjacentText メソッドを呼び出します。可能な値がすべてリストされています ここ:
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);
c#からWebBrowser Control HTMLドキュメントにJavascriptを挿入する最も簡単な方法は、<!> quot; execStrip <!> quot;を呼び出すことです。引数として挿入されるコードを持つメソッド。
この例では、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コントロールに有効です。
<!> quot; execScript <!> quot; 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();
希望する
これを使用しました: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コントロールに読み込まれたページ内から変数の値を取得しようとしている場合のVB.Netの例を次に示します。
ステップ1)プロジェクトのCOM参照をMicrosoft HTML Object Libraryに追加します
ステップ2)次に、このVB.NetコードをForm1に追加してmshtmlライブラリをインポートします:
mshtmlをインポートします
ステップ3)<!> quot; Public Class Form1 <!> quot;の上にこのVB.Netコードを追加します。行:
<!> lt; System.Runtime.InteropServices.ComVisibleAttribute(True)<!> gt;
ステップ4)WebBrowserコントロールをプロジェクトに追加します
ステップ5)このVB.NetコードをForm1_Load関数に追加します:
WebBrowser1.ObjectForScripting = Me
ステップ6)関数<!> quot; CallbackGetVar <!> quot;を挿入するこのVB.Netサブを追加します。 Webページの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 <!> quot; eval <!> quot;を読んでください。これを可能にするのは、ステップ6で使用される関数です。文字列を受け取り、その名前の変数が存在するかどうかを判断し、存在する場合はその変数の値を返します。
常に<!> quot; DocumentStream <!> quot;を使用できます。または<!> quot; DocumentText <!> quot;プロパティ。 HTMLドキュメントを使用するには、 HTML Agility Pack をお勧めします。
やりたいことは、Page.RegisterStartupScript(key、script)を使用することです :
詳細については、こちらをご覧ください: http://msdn.microsoft.com /en-us/library/aa478975.aspx
基本的に行うことは、javascript文字列を作成し、そのメソッドに渡し、一意のidを与えることです(ページで2回登録する場合)。
編集:これは、トリガーハッピーと呼びます。お気軽にどうぞ。 :)
iを使用:
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
をインポートすることを忘れないでください。これがお役に立てば幸いです。