如何检测 WebBrowser 控件中的 Javascript 执行

Posted

技术标签:

【中文标题】如何检测 WebBrowser 控件中的 Javascript 执行【英文标题】:How to detect Javascript execution in WebBrowser control 【发布时间】:2012-03-22 23:42:34 【问题描述】:

我的 C# 应用程序中有一个 WebBrowser 控件。网络浏览器在用户的控制之下,即他可以在网络上加载他的电脑可以访问的任何网页(当然受限于代理、hosts文件等)。

当网页浏览器组件中加载的页面内有 javascript 调用时,我需要知道并得到通知。

第一个例子:给定这样的链接

<a href="javascript:void(0)" onclick="jsFunct();">test</a>

当用户点击链接时,我需要知道函数“jsFunct”已被调用。

第二个例子:给定一个电话

<script type="text/javascript">
    window.setTimeout("jsFunct()", 1000);
</script>

我需要知道,脚本执行后1秒,函数jsFunct已经被调用。

最好的办法是在函数被调用时触发一个事件。如果事件可以执行 Javascript 代码,或者至少是参数中的函数名,那也很棒。

编辑:

即使问题与 webbrowser 组件有关,任何允许用户检测 javascript 激活(甚至通过 js)的东西都可以,能够注入处理 javascript 事件并将其传递给 wb 控件的 js触发一些它可以处理的事件。

【问题讨论】:

【参考方案1】:

当在 JavaScript 中触发全局函数时,您可以使用 window.external 调用 C# 方法。有关 window.external 的详细信息,请参阅WebBrowser Control Overview。

您需要设置 ObjectForScripting: Webbrowser control's window.external is ALWAYS null. 才能使其工作。

采用@Krishna 的回答来添加 JavaScript(但删除 jQuery,因为它不需要):

private void addScript(htmlElement head, string scriptSource) 
 
HtmlElement lhe_script = head.Document.CreateElement("script"); 
IHTMLScriptElement script = (IHTMLScriptElement)lhe_script.DomElement; 
script.src = scriptSource;
head.AppendChild(lhe_script);            
 

addScript(WebBrowser.Head, @"InjectMonitor.js");

下面的 JavaScript (InjectMonitor.js) 将查找所有全局函数并附加您指定的处理程序:

function augment(withFn) 
    var name, fn;
    for (name in window) 
        fn = window[name];
        if (typeof fn === 'function') 
            window[name] = (function(name, fn) 
                var args = arguments;
                return function() 
                    withFn.apply(this, args);
                    fn.apply(this, arguments);

                ;
            )(name, fn);
        
    


augment(function(name, fn) 
    console.log("calling " + name, fn);

    // window.external.yourC#method
);

在这个例子中,取自Adding Console Log to Every Function,它只是记录对控制台的调用;但是使用 window.external 您可以将一些消息发送回您的 C# 应用程序,其中包含从客户端调用的函数的详细信息。

最后,这是一个 JS Bin 示例(运行它,不要忘记控制台):JS Bin Example

【讨论】:

目前我没有太多时间来测试这个,你能解释一下我如何用window.external 检测到网页中对特定js函数的调用吗?一个小的代码示例也将不胜感激 已更新,我添加了相关的 JS 并希望完整的解决方案。 正是我所需要的,真的很高兴奖励赏金并解决这个问题,谢谢! 没问题,仅供参考,我曾经玩过 Function.prototype.call 认为可以做到这一点,但除非调用 call(),否则永远无法让它工作。 什么是WebBrowser.Head?这是一个例子,你的意思是WebBrowser.Document.GetElementsByTagName("head")[0]?【参考方案2】:

在浏览器加载事件上,

    注入 Jquery 注入监控脚本

private void addScript(HtmlElement head, string scriptSource) 
 
HtmlElement lhe_script = head.Document.CreateElement("script"); 
IHTMLScriptElement script = (IHTMLScriptElement)lhe_script.DomElement; 
script.src = scriptSource;
head.AppendChild(lhe_script);            
 

addScript(Webbrowser.Head, @"<Change File Path here>jquery.min.js");
addScript(WebBrowser.Head, @"InjectMonitor.js");

您的文件 InjectMonitor.js 应该是这样的

 $(document).ready(function ()  
        //Add click event for every anchor on the page loaded- note this merely alerts text on click. you can however add your own function
        $("a").click(function (e)  alert($(this).text()); return false;) 
    ); 

【讨论】:

+1 为我指明了正确的方向,让我们做更多的工作来得到答案 请告诉我你们相处得如何。如果你被困在某个地方,我也会尝试在我的最后设置这个项目。这是一个很好的,相信很有可能 您能更好地解释一下“监控脚本”是什么意思吗?谢谢 jQuery 支持同一事件的多个处理程序,因此如果您想知道某人何时单击了某个锚点(例如),您可以将代码添加到 MonitorScript(请参阅上面我编辑的答案) 我相信这就是帖子所说的,包装对 webbrowser 代码中加载的现有 javascript 代码(不在您的控制范围内)的额外调用。即,对于页面中的每个 javascript 函数,向您的侦听器注入一个调用(这是/将在 MonitorScript.js 中定义)。让我看看我是否可以为您获取此代码。我这周不在,但这将是一项值得思考的好任务【参考方案3】:

克里希纳回答的是纯 javascript 附加到事件,但是我看到您可能需要将它附加到所有标签(a、p、div、输入)等以及附加到每个标签的所有事件.

我相信另一种方法是使用 .net 中可用的 BHO(浏览器帮助对象),如果没有,并且您擅长 VC++ 和 MFC,您也可以使用 Windows Hooks。

【讨论】:

将javascript附加到事件的问题是它没有检测到使用setTimeout之类的函数执行的javascript的执行。此外,如果点击没有触发 javascript 调用怎么办?不好。无论何时发生,我都需要检测 JavaScript 函数的执行,它应该在事件处理程序中调用,由超时触发还是以其他方式触发。

以上是关于如何检测 WebBrowser 控件中的 Javascript 执行的主要内容,如果未能解决你的问题,请参考以下文章

检测 WebBrowser 完整页面加载

在 WebBrowser 控件中检测滚动到底部

如何从托管 WebBrowser 控件的应用程序调用 WebBrowser 控件查看的页面中的 JavaScript 函数?

如何在 C# 中更新 WebBrowser 控件中的 DOM 内容?

如何禁用 .NET WebBrowser 控件中的缓存?

如何单击 webbrowser 控件中的按钮?