Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从WebBrowser中文档中的JavaScript调用C#代码_C#_.net_Javascript - Fatal编程技术网

从WebBrowser中文档中的JavaScript调用C#代码

从WebBrowser中文档中的JavaScript调用C#代码,c#,.net,javascript,C#,.net,Javascript,我有一个C#WinForms应用程序,其中有一个WebBrowser控件。我想在我的C#表单和嵌入式web浏览器控件中的JavaScript之间执行双向通信 我知道我可以用调用JavaScript函数,但是如何在一个脚本中调用JavaScript中的C#代码呢?我想,由于安全原因,这并不容易,但无论如何,这有可能吗? 这些JavaScript函数应该是用户函数,非常类似于宏,它可以告诉WebBrowser在我自己编写的整个C#库的帮助下做什么。由于这是一个web scraper,JavaScri

我有一个C#WinForms应用程序,其中有一个WebBrowser控件。我想在我的C#表单和嵌入式web浏览器控件中的JavaScript之间执行双向通信

我知道我可以用调用JavaScript函数,但是如何在一个脚本中调用JavaScript中的C#代码呢?我想,由于安全原因,这并不容易,但无论如何,这有可能吗?
这些JavaScript函数应该是用户函数,非常类似于宏,它可以告诉WebBrowser在我自己编写的整个C#库的帮助下做什么。由于这是一个web scraper,JavaScript是这些宏的完美语言,因为它几乎可以访问HTML文档中的元素

您需要做的是将web浏览器控件上的
ObjectForScripting
属性设置为包含要从JavaScript调用的C#方法的对象。然后可以使用
window.external
从JavaScript访问该对象。唯一需要注意的是对象必须具有
[ComVisibleAttribute(true)]
属性。我已经成功地使用它好几年了

下面是一个包含文档的页面和一个简单的示例:

下面是链接中的示例(我没有尝试过此代码):

使用系统;
使用System.Windows.Forms;
使用System.Security.Permissions;
[权限集(SecurityAction.Demand,Name=“FullTrust”)]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
公开课表格1:表格
{
私有WebBrowser webBrowser1=新WebBrowser();
私有按钮button1=新按钮();
[状态线程]
公共静态void Main()
{
Application.EnableVisualStyles();
Application.Run(新Form1());
}
公共表格1()
{
button1.Text=“从客户端代码调用脚本代码”;
button1.Dock=DockStyle.Top;
button1.Click+=新建事件处理程序(button1\u Click);
webBrowser1.Dock=DockStyle.Fill;
控件。添加(webBrowser1);
控件。添加(按钮1);
Load+=新事件处理程序(Form1_Load);
}
私有void Form1\u加载(对象发送方、事件参数e)
{
webBrowser1.AllowWebBrowserDrop=false;
webBrowser1.IsWebBrowserContextMenuEnabled=false;
webBrowser1.WebBrowserShortcutsEnabled=false;
webBrowser1.ObjectForScript=此;
//完成调试后,取消对以下行的注释。
//webBrowser1.ScriptErrorsSuppressed=true;
webBrowser1.DocumentText=
"" +
“功能测试(消息){警报(消息);}”+
"" +
“从脚本代码调用客户端代码”+
"";
}
公共无效测试(字符串消息)
{
MessageBox.Show(消息,“客户端代码”);
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
webBrowser1.Document.InvokeScript(“测试”,
新字符串[]{“从客户端代码调用”});
}
}

您可能正在寻找

WebBrowser.ObjectForScript允许您将[ComVisible].net类的实例公开给托管web浏览器中运行的javascript代码。它在javascript中作为
窗口公开。外部

来自微软的优秀文章:

以下是我编写的一些扩展方法,它们有助于WebBrowser对象和C代码之间的双向通信/调用:

使用系统;
使用系统线程;
使用FluentSharp.Web35;
使用FluentSharp.WinForms;
使用FluentSharp.CoreLib;
使用FluentSharp.CoreLib.API;
名称空间FluentSharp.Watin
{
公共静态类WatiN\u IE\u ExtensionMethods\u Javascript
{
公共静态对象invokeScript(这个WatiN_IE,字符串functionName)
{
返回ie.invokeScript(functionName,null);
}
公共静态对象invokeScript(此WatiN_IE,字符串functionName,params object[]参数)
{
//“[WatiN_IE]调用带有参数的脚本{0}:{1}”.info(functionName,parameters.size());
返回ie.invokeScript(true,functionName,parameters);
}   
公共静态对象invokeScript(此WatiN_IE,bool waitForExecutionComplete,字符串functionName,params object[]参数)
{
var sync=新的自动重置事件(false);
对象响应值=null;
ie.WebBrowser.invokeOnThread(
()=>{
var document=ie.WebBrowser.document;
if(parameters.isNull())
responseValue=document.InvokeScript(函数名);
其他的
responseValue=document.InvokeScript(函数名、参数);
sync.Set();
});
如果(waitForExecutionComplete)
sync.WaitOne();
返回响应值;
}
公共静态对象invokeEval(这个WatiN_IE,string evalScript)
{
var evalParam=“(函数(){“+evalScript+”})(;”;
//“[WatiN_IE]invokeEval evalParam:{0}”。调试(evalParam);
返回ie.invokeScript(“eval”,evalParam);
}
公共静态WatiN_IE.java脚本函数(此WatiN_IE)
{
返回ie.injectJavascriptFunctions(false);
}
公共静态WatiN_IE.tocJavaScriptFunctions(此WatiN_IE,bool resetHooks)
{
if(即WebBrowser.isNull())
“在InjectJavascriptFunctions中,ie.WebBrowser为null”。错误();
其他的
{
if(即.WebBrowser.ObjectForScripting.isNull()| | resetHooks)
{
ie.WebBrowser.ObjectForScripting=new WatiN_ie.ToCSharp();
为页面{0}注入Javascript钩子*函数
using System;
using System.Windows.Forms;
using System.Security.Permissions;

[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class Form1 : Form
{
    private WebBrowser webBrowser1 = new WebBrowser();
    private Button button1 = new Button();

    [STAThread]
    public static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }

    public Form1()
    {
        button1.Text = "call script code from client code";
        button1.Dock = DockStyle.Top;
        button1.Click += new EventHandler(button1_Click);
        webBrowser1.Dock = DockStyle.Fill;
        Controls.Add(webBrowser1);
        Controls.Add(button1);
        Load += new EventHandler(Form1_Load);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.AllowWebBrowserDrop = false;
        webBrowser1.IsWebBrowserContextMenuEnabled = false;
        webBrowser1.WebBrowserShortcutsEnabled = false;
        webBrowser1.ObjectForScripting = this;
        // Uncomment the following line when you are finished debugging.
        //webBrowser1.ScriptErrorsSuppressed = true;

        webBrowser1.DocumentText =
            "<html><head><script>" +
            "function test(message) { alert(message); }" +
            "</script></head><body><button " +
            "onclick=\"window.external.Test('called from script code')\">" +
            "call client code from script code</button>" +
            "</body></html>";
    }

    public void Test(String message)
    {
        MessageBox.Show(message, "client code");
    }

    private void button1_Click(object sender, EventArgs e)
    {
        webBrowser1.Document.InvokeScript("test",
            new String[] { "called from client code" });
    }
}
using System;
using System.Threading;
using FluentSharp.Web35;
using FluentSharp.WinForms;
using FluentSharp.CoreLib;
using FluentSharp.CoreLib.API;

namespace FluentSharp.Watin
{
    public static class WatiN_IE_ExtensionMethods_Javascript
    {

        public static object invokeScript(this WatiN_IE ie, string functionName)
        {
            return ie.invokeScript(functionName, null);
        }

        public static object invokeScript(this WatiN_IE ie, string functionName, params object[] parameters)
        {
            //"[WatiN_IE] invokeScript '{0}' with parameters:{1}".info(functionName ,parameters.size());
            return ie.invokeScript(true, functionName, parameters);
        }   

        public static object invokeScript(this WatiN_IE ie, bool waitForExecutionComplete, string functionName, params object[] parameters)
        {
            var sync = new AutoResetEvent(false);
            object responseValue = null;
            ie.WebBrowser.invokeOnThread(
                ()=>{
                        var document = ie.WebBrowser.Document;
                        if (parameters.isNull())
                            responseValue = document.InvokeScript(functionName); 
                        else
                            responseValue = document.InvokeScript(functionName, parameters); 
                        sync.Set(); 
                });
            if (waitForExecutionComplete)
                sync.WaitOne();
            return responseValue;   
        }

        public static object invokeEval(this WatiN_IE ie, string evalScript)
        {
            var evalParam = "(function() { " + evalScript + "})();";
            //"[WatiN_IE] invokeEval evalParam: {0}".debug(evalParam);
            return ie.invokeScript("eval", evalParam);   
        }
        public static WatiN_IE.ToCSharp injectJavascriptFunctions(this WatiN_IE ie)
        {
            return ie.injectJavascriptFunctions(false);
        }

        public static WatiN_IE.ToCSharp injectJavascriptFunctions(this WatiN_IE ie, bool resetHooks)
        {
            if (ie.WebBrowser.isNull())
                "in InjectJavascriptFunctions, ie.WebBrowser was null".error();
            else
            {
                if (ie.WebBrowser.ObjectForScripting.isNull() || resetHooks)  
                {
                    ie.WebBrowser.ObjectForScripting = new WatiN_IE.ToCSharp();

                    "Injecting Javascript Hooks * Functions for page: {0}".debug(ie.url());
                    ie.eval("var o2Log = function(message) { window.external.write(message) };");
                    ie.invokeScript("o2Log","Test from Javascript (via toCSharp(message) )");
                    ie.eval("$o2 = window.external");
                    "Injection complete (use o2Log(...) or $o2.write(...)  to talk back to O2".info();
                    return (ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp);
                }
                else 
                {
                    if((ie.WebBrowser.ObjectForScripting is WatiN_IE.ToCSharp))
                        return (ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp);
                    else
                        "in WatiN_IE injectJavascriptFunctions, unexpected type in ie.WebBrowser.ObjectForScripting: {0}".error(ie.WebBrowser.ObjectForScripting.typeName());                   
                }

            }
            return null;
        }

        public static object downloadAndExecJavascriptFile(this WatiN_IE ie, string url)
        {
            "[WatiN_IE] downloadAndExecJavascriptFile: {0}".info(url);
            var javascriptCode = url.uri().getHtml();
            if (javascriptCode.valid())
                ie.eval(javascriptCode);
            return ie;
        }

        public static WatiN_IE injectJavascriptFunctions_onNavigate(this WatiN_IE ie)
        {

            ie.onNavigate((url)=> ie.injectJavascriptFunctions());
            return ie;
        }

        public static WatiN_IE setOnAjaxLog(this WatiN_IE ie, Action<string, string,string,string> onAjaxLog)
        {
            (ie.WebBrowser.ObjectForScripting as WatiN_IE.ToCSharp).OnAjaxLog = onAjaxLog;
            return ie;
        }

        public static WatiN_IE eval_ASync(this WatiN_IE ie, string script)
        {
            O2Thread.mtaThread(()=> ie.eval(script));
            return ie;
        }

        public static WatiN_IE eval(this WatiN_IE ie, string script)
        {
            return ie.eval(script, true);
        }

        public static WatiN_IE eval(this WatiN_IE ie, string script, bool waitForExecutionComplete)
        {
            var executionThread = O2Thread.staThread(()=> ie.IE.RunScript(script));         
            if (waitForExecutionComplete)
                executionThread.Join();
            return ie;  
        }

        public static WatiN_IE alert(this WatiN_IE ie, string alertScript)
        {
            return ie.eval("alert({0});".format(alertScript));
        }

        public static object getJsObject(this WatiN_IE ie)
        {
            var toCSharpProxy = ie.injectJavascriptFunctions();
            if (toCSharpProxy.notNull())
                return toCSharpProxy.getJsObject();
            return null;        
        }

        public static T getJsObject<T>(this WatiN_IE ie, string jsCommand)
        {
            var jsObject = ie.getJsObject(jsCommand);
            if (jsObject is T)
                return (T)jsObject;
            return default(T);
        }

        public static bool doesJsObjectExists(this WatiN_IE ie, string jsCommand)
        {
            var toCSharpProxy = ie.injectJavascriptFunctions();
            if (toCSharpProxy.notNull())
            {
                var command = "window.external.setJsObject(typeof({0}))".format(jsCommand);
                ie.invokeEval(command);
                ie.remapInternalJsObject();             
                return toCSharpProxy.getJsObject().str()!="undefined";
            }
            return false;
        }

        public static object getJsVariable(this WatiN_IE ie, string jsCommand)
        {
            return ie.getJsObject(jsCommand);
        }

        public static object getJsObject(this WatiN_IE ie, string jsCommand)
        {
            var toCSharpProxy = ie.injectJavascriptFunctions();
            if (toCSharpProxy.notNull())
            {
                var command = "window.external.setJsObject({0})".format(jsCommand);
                ie.invokeEval(command);
                ie.remapInternalJsObject();             
                return toCSharpProxy.getJsObject();
            }
            return null;
        }               

        public static WatiN_IE remapInternalJsObject(this WatiN_IE ie)
        {       
            //"setting JS _jsObject variable to getJsObject()".info();
            ie.invokeEval("_jsObject = window.external.getJsObject()"); // creates JS variable to be used from JS
            return ie;
        }

        public static WatiN_IE setJsObject(this WatiN_IE ie, object jsObject)
        {
            var toCSharpProxy = ie.injectJavascriptFunctions();
            if (toCSharpProxy.notNull())            
            {
                toCSharpProxy.setJsObject(jsObject);
                ie.remapInternalJsObject();
            }
            return ie;
        }

        public static object waitForJsObject(this WatiN_IE watinIe)
        {
            return watinIe.waitForJsObject(500, 20);
        }

        public static object waitForJsObject(this WatiN_IE watinIe, int sleepMiliseconds, int maxSleepTimes)
        {                   
            "[WatiN_IE][waitForJsObject] trying to find jsObject for {0} x {1} ms".info(maxSleepTimes, sleepMiliseconds);
            watinIe.setJsObject(null);
            for(var i = 0; i < maxSleepTimes ; i++)
            {
                var jsObject = watinIe.getJsObject();
                if(jsObject.notNull())
                {
                    "[watinIe][waitForJsObject] got value: {0} (n tries)".info(jsObject, i);
                    return jsObject;
                }

                watinIe.sleep(500, false);
            }
            "[WatiN_IE][waitForJsObject] didn't find jsObject after {0} sleeps of {1} ms".error(maxSleepTimes, sleepMiliseconds);
            return null;
        }

        public static object waitForJsVariable(this WatiN_IE watinIe, string jsCommand)
        {
            return watinIe.waitForJsVariable(jsCommand,  500, WatiN_IE_ExtensionMethods.WAITFORJSVARIABLE_MAXSLEEPTIMES);
        }

        public static object waitForJsVariable(this WatiN_IE watinIe, string jsCommand, int sleepMiliseconds, int maxSleepTimes)
        {   
            "[WatiN_IE][waitForJsVariable] trying to find jsObject called '{0}' for {1} x {2} ms".info(jsCommand, maxSleepTimes, sleepMiliseconds);         
            watinIe.setJsObject(null);
            for(var i = 0; i < maxSleepTimes ; i++)
            {
                if (watinIe.doesJsObjectExists(jsCommand))
                {
                    var jsObject = watinIe.getJsObject(jsCommand);
                    "[watinIe][waitForJsVariable] got value: {0} ({1} tries)".info(jsObject, i);
                    return jsObject;
                }                   
                watinIe.sleep(500, false);
            }
            "[WatiN_IE][waitForJsVariable] didn't find jsObject called '{0}' after {1} sleeps of {2} ms".error(jsCommand, maxSleepTimes, sleepMiliseconds);
            return null;
        }

        public static WatiN_IE deleteJsVariable(this WatiN_IE watinIe, string jsVariable)
        {
            var evalString = "try { delete " + jsVariable + " } catch(exception) { }";
            watinIe.eval(evalString);
            return watinIe;
        }


    }
}