WebBrowserコントロールにJavascriptを挿入する方法は?


81

私はこれを試しました:

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に挿入する簡単な方法はありますか?

回答:


101

何らかの理由で、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インターフェイスをプロジェクトに組み込む方法を説明しています。


1
かっこいいです。IHTMLScriptElementを使用すると、どのような場合でもコードの意図がより明確になると思います。なぜ例外が発生したのか疑問に思いますが、COM相互運用機能を使用する場合があります。
ZeroBugBounce 2008

ローカルのjsファイルへの参照を追加するのはどうですか?stackoverflow.com/questions/4029602/を

これを手伝ってください。どうやってこれをしましたか。C ++アプリを使用してJSをページにリアルタイムで挿入したいと思います。どうすればいいですか。
Johnydep 2011年

これはjqueryファイルの挿入にも適用できますか?
グムル

51
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フォームアプリでテスト済み)

編集:関数セットのケースの問題を修正しました。


12
(便利ではありますが!)IHTMLSCriptElementアセンブリに依存しないため、このソリューションを高く評価しました。
ミカ・スミス

6
@jsightこれは受け入れられた答えであるはずです。これは現在の回答と同じですが、より単純でIHTMLSCriptElement依存関係がありません。
BlueRaja-Danny Pflughoeft 2013

32

これに取り組んだ後に私が見つけた最も簡単な方法は次のとおりです。

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に記述されているものをすべて解析して実行することです。ここでw3schoolsrefを確認してください。


22

また、.NET 4では、dynamicキーワードを使用すると、これはさらに簡単になります。

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

2
なぜ誰かがそのためにダイナミックを必要とするのでしょうか?タイピングを節約しようとしている場合は、C#3.0以降、型推論が行われているため、varを使用できます。DLRの呼び出しを開始する必要はありません。
alimbada 2010

23
これは基本的に、動的キーワードであるCOM相互運用のポイントです。ここには実際には型推論はありません。ドキュメントがあります。たとえば、IHTMLElement2はIHtmlElementから割り当てることができず、実行時にはCOMプロキシオブジェクトがあるだけです。どのインターフェースを何にキャストするかを知る必要があります。動的キーワードは、その雑然としたものの多くを削減するのに役立ちます。メソッドが存在することを知っていますか?なぜそれを何らかのインターフェースにキャストするのですか?'DLRを正確に呼び出すわけではありません' COMオブジェクト(この場合)でメソッドを呼び出す方法を知っているコードを生成するだけです。
justin.m.chase 2010

1
@ justin.m.chaseあなたは私の命を救った。
Khizar Iqbal 2017

17

本当に必要なのがjavascriptを実行することだけである場合、これが最も簡単です(VB .Net):

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

これはそれを「注入」しないと思いますが、それがあなたが求めているものであれば、それはあなたの関数を実行します。(問題を複雑にしすぎた場合に備えて。)そして、javascriptに挿入する方法が理解できる場合は、それを関数 "foo"の本体に入れて、javascriptに挿入を任せます。


10

HTMLドキュメントのマネージラッパーは、必要な機能を完全には実装していないため、MSHTML APIにアクセスして、必要な機能を実行する必要があります。

1)MSHTMLへの参照を追加します。これは、COM参照の下で「MicrosoftHTMLオブジェクトライブラリ」と呼ばれる可能性があります。

2)「mshtmlを使用して」を追加します。名前空間に。

3)スクリプト要素のIHTMLElementへの参照を取得します。

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4)最初のパラメーター値を「afterBegin」にしてinsertAdjacentTextメソッドを呼び出します。可能なすべての値がここにリストされています

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

5)これで、scriptEl.InnerTextプロパティにコードが表示されるようになります。

Hth、リチャード


1
いいですね...これは、korchevが提供するヒントと合わせて完璧に機能します。私はこれに2つの受け入れられた解決策を設定できればいいのにと思います。:)
jsight 2008

8

受け入れられた回答のフォローアップとして、これは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");
            }
        }
    }
}

8

c#からWebBrowser Control HTMLドキュメントにJavascriptを挿入する最も簡単な方法は、引数として挿入するコードを使用して「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フォームおよびWPFWebBrowserコントロールに有効です。

「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();

それが役に立てば幸い


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

2
これはコミュニティリソースであるため、彼の回答は他の人(私のような)にも役立ちます。mshtmlに相当する+1は、私に質問を保存しました。
Kyeotic 2011

1
これを見つけた人は、最後の行から「class」を削除してください((HTMLHeadElement)head).appendChild((IHTMLDOMNode)scriptObject);。そうしないとエラーが発生します。
Kyeotic 2011

1
とにかく、この回答は管理者によって宣伝される可能性がありますか?これより上のものはすべて実際には間違っています。これは遅刻でしたが、本当に最も正しい答えです。
justin.m.chase 2012

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

お役に立てれば幸いです


2

WebBrowserコントロールにロードされたページ内から変数の値を取得しようとしている場合のVB.Netの例を次に示します。

手順1)プロジェクトのCOM参照をMicrosoftHTMLオブジェクトライブラリに追加します

ステップ2)次に、MSHTMLライブラリをインポートするためにあなたのForm1に、このVB.Netコードを追加します。
輸入はMSHTML

手順3)次のVB.Netコードを「PublicClassForm1」行の上に追加します。
<System.Runtime.InteropServices.ComVisibleAttribute(True)>

ステップ4)プロジェクトにWebBrowserコントロールを追加します

ステップ5)このVB.NetコードをForm1_Load関数に追加します:
WebBrowser1.ObjectForScripting = Me

ステップ6)このVB.Netサブを追加して、関数「CallbackGetVar」を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)Javascriptが呼び出されたときに検索する次のVB.Netサブを追加します。

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」関数を読んでください。これがこれを可能にします。文字列を受け取り、その名前の変数が存在するかどうかを判断し、存在する場合は、その変数の値を返します。


1

「DocumentStream」または「DocumentText」プロパティはいつでも使用できます。HTMLドキュメントを操作するには、HTML AgilityPackをお勧めします


良いヒント... libはいつか役立つと確信しています。
jsight 2008

1

私はこれを使用します:

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

0

あなたがしたいことはPage.RegisterStartupScript(key、script)を使用することです:

詳細については、こちらを参照してください:http//msdn.microsoft.com/en-us/library/aa478975.aspx

基本的に行うことは、JavaScript文字列を作成し、それをそのメソッドに渡して、一意のIDを与えることです(ページに2回登録しようとした場合)。

編集:これはあなたがトリガーハッピーと呼ぶものです。お気軽にどうぞ。:)


4
ASP.Netは、winformsアプリでWebBrowserコントロールをスクリプト化することとはあまり関係がありません。
jsight 2008

私はおそらく同じように読み
すぎ

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。これがお役に立てば幸いです。


これは1年前の3日前に回答されたと思いますが、これを使用してファイルをinput type="file"セクションに入れることはできますか?
クリス・ホッブズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.