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 interop과 경쟁합니다.
ZeroBugBounce

로컬 js 파일에 대한 참조를 추가하는 것은 어떻습니까? stackoverflow.com/questions/4029602/를
IAmAN00B

이걸 도와주세요. 어떻게 하셨어요? 내 C ++ 앱을 통해 실시간으로 내 페이지에 JS를 삽입하고 싶습니다. 어떻게해야하나요?
Johnydep 2011-06-03

jquery 파일을 삽입하는데도 적용됩니까?
gumuruh

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 Forms 앱에서 테스트 됨)

편집 : 기능 세트의 케이스 문제를 수정했습니다.


12
이 솔루션은 유용하지만 IHTMLSCriptElement 어셈블리에 의존하지 않기 때문에 감사했습니다.
Micah Smith

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에 작성된 모든 것을 구문 분석하고 실행하는 것입니다. 여기에서 w3schools ref를 확인 하십시오 .


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 interop의 요점입니다. 여기에는 실제로 유형 추론이 없으며 문서가 있습니다. 예를 들어 IHTMLElement2는 IHtmlElement에서 할당 할 수 없기 때문에 런타임에는 COM 프록시 개체 만 있습니다. 어떤 인터페이스를 무엇으로 캐스팅해야하는지 알아야합니다. dynamic 키워드는 이러한 문제를 줄이는 데 도움이됩니다. 방법이 존재하는 이유를 알고 있습니다. 정확히 'DLR을 호출'하는 것이 아니라 COM 개체 (이 경우)에서 메서드를 호출하는 방법을 아는 코드를 생성 할뿐입니다.
justin.m.chase 2010

1
@ justin.m.chase 당신이 내 생명을 구했습니다.
Khizar Iqbal

17

정말로 원하는 것이 자바 스크립트를 실행하는 것이라면 이것이 가장 쉬울 것입니다 (VB .Net).

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

나는 이것이 그것을 "주입"하지 않을 것이라고 생각하지만 그것이 당신이 추구하는 것이라면 당신의 함수를 실행할 것입니다. (문제를 지나치게 복잡하게 만든 경우를 대비하여.) 그리고 자바 스크립트에서 주입하는 방법을 알아낼 수 있다면이를 "foo"함수의 본문에 넣고 자바 스크립트가 자동으로 주입하도록하십시오.


10

HTML 문서에 대한 관리되는 래퍼는 필요한 기능을 완전히 구현하지 않으므로 원하는 작업을 수행하려면 MSHTML API를 살펴 봐야합니다.

1) COM 참조 에서 "Microsoft HTML Object Library"라고하는 MSHTML에 대한 참조를 추가합니다 .

2) 'using mshtml;'추가 네임 스페이스에.

3) 스크립트 요소의 IHTMLElement에 대한 참조를 가져옵니다.

IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;

4) 첫 번째 매개 변수 값이 "afterBegin"인 insertAdjacentText 메소드를 호출합니다. 가능한 모든 값은 다음과 같습니다 .

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

5) 이제 scriptEl.InnerText 속성에서 코드를 볼 수 있습니다.

Hth, Richard


1
멋지다 ... korchev가 제공하는 팁과 함께 완벽하게 작동합니다. 나는 이것에 대해 두 가지 허용되는 솔루션을 설정할 수 있기를 바랍니다. :)
jsight

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"메서드를 호출하는 것입니다.

이 예에서 자바 스크립트 코드는 전역 범위에서 삽입되고 실행됩니다.

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는 지원되는 유일한 것입니다.

자바 스크립트 코드를 삽입하기위한 유효한 크로스 브라우저 메소드의 경우 새 키워드를 사용하여 Function 개체를 만듭니다. 이 예제는 삽입 된 코드로 익명 함수를 만들고 실행합니다 (자바 스크립트는 클로저를 구현하고 함수는 지역 변수 오염없이 전역 공간에 액세스 할 수 있음).

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-09-12

1
이것을 발견하는 사람은 마지막 줄에서 'class'를 제거하십시오 ((HTMLHeadElement)head).appendChild((IHTMLDOMNode)scriptObject);. 그렇지 않으면 오류가 발생합니다.
Kyeotic 2011-09-12

1
어쨌든이 답변은 관리자가 홍보 할 수 있습니까? 위의 것들은 실제로 모두 잘못되었습니다. 이것은 늦게 왔지만 실제로 가장 정답입니다.
justin.m.chase dec.

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 참조를 Microsoft HTML 개체 라이브러리에 추가

2 단계) 다음으로이 VB.Net 코드를 Form1에 추가하여 mshtml 라이브러리를 가져옵니다.
Imports mshtml

3 단계) "Public Class Form1"줄 위에 다음 VB.Net 코드를 추가합니다.
<System.Runtime.InteropServices.ComVisibleAttribute (True)>

4 단계) 프로젝트에 WebBrowser 컨트롤 추가

5 단계)이 VB.Net 코드를 Form1_Load 함수에 추가합니다.
WebBrowser1.ObjectForScripting = Me

6 단계) 웹 페이지의 Javascript에 "CallbackGetVar"함수를 삽입 할이 VB.Net 하위를 추가합니다.

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 Agility Pack을 권장합니다 .


좋은 팁 ... 나는 lib가 언젠가는 유용 할 것이라고 확신합니다.
jsight

1

나는 이것을 사용한다 :

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

0

원하는 것은 Page.RegisterStartupScript (key, script) 사용하는 것입니다.

자세한 내용은 여기를 참조하십시오 : http://msdn.microsoft.com/en-us/library/aa478975.aspx

기본적으로하는 일은 자바 스크립트 문자열을 빌드하고 해당 메소드에 전달하고 고유 한 ID를 부여하는 것입니다 (페이지에 두 번 등록하려는 경우).

편집 : 이것은 당신이 트리거 행복이라고 부르는 것입니다. 그것을 내려 주시기 바랍니다. :)


4
ASP.Net은 winforms 앱에서 WebBrowser 컨트롤을 스크립팅하는 것과 많은 관련이 없습니다.
jsight

나는 아마도 같은 방식으로 읽고 똑같은 오답을
주었을

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"섹션에 넣을 수 있습니까?
Chris Hobbs 2015
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.