如何检测 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 控件查看的页面中的 JavaScript 函数?