这将是相当骇客,但我分享无论如何。我创建了一个简单的例子,对我很有用,我希望它也能帮助你。
JavaScript端只是一个普通的HTML,带有一个按钮,点击后调用事件处理程序:
指数html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Test</title>
<script src="app.js"></script>
</head>
<body>
<button onclick="onClick()">Click me</button>
</body>
</html>
事件处理程序只调用一个随机函数(甚至不必存在于
frameElement
)带有一些参数:
应用程序。js公司
function onClick() {
var x = window.frameElement.greet("Hello", "world");
}
C侧具有
ChromiumWebBrowser
指向我的页面地址:
Form1.Designer。反恐精英
this.browser = new CefSharp.WinForms.ChromiumWebBrowser("http://localhost:3000/index.html");
我订阅
FrameLoadEnd
事件:
this.browser.FrameLoadEnd += BrowserOnFrameLoadEnd;
处理程序将一些JavaScript代码注入主/顶部框架(我们的主页):
Form1.cs
private void BrowserOnFrameLoadEnd(object sender, FrameLoadEndEventArgs frameLoadEndEventArgs)
{
if (frameLoadEndEventArgs.Frame.IsMain)
{
frameLoadEndEventArgs.Frame.ExecuteJavaScriptAsync(@"
(function() {
Object.defineProperty(window, 'frameElement', {
writable: true
});
window.frameElement = {};
window.frameElement = new Proxy(window.frameElement, {
get: function (target, propKey, receiver) {
return function(...args) {
window.frameElementInterceptor.intercept(propKey, args);
};
}
});
})();");
}
}
注入的代码修改
window.frameElement
使用
ES6 Proxy
. 当原始页面
window.frameElement.someMethod(arg1, arg2)
我可以注入自定义逻辑。
我注入的自定义逻辑是调用
frameElementInterceptor
的
intercept
方法,其中包含调用的函数名和传入的参数。
回到C端,我们在CEFSharp浏览器中注册了一个JS对象,并将其作为
frameElementInterceptor框架元素拦截器
关于JS中的全局范围:
[ComVisible(true)]
public class FrameElementInterceptor
{
public void Intercept(string propKey, object[] args)
{
MessageBox.Show($@"Function '{propKey}' was called with arguments: [{string.Join(", ", args)}]",
@"Function call intercepted");
}
}
public Form1()
{
InitializeComponent();
// .....
browser.RegisterJsObject("frameElementInterceptor", new FrameElementInterceptor());
}
现在所有的部分都准备好了,每当我单击页面中的按钮时,我的C#拦截器就会收到消息:
警告
:虽然这个简单的示例有效,但我确信这里没有考虑各种边缘情况,因此我会非常谨慎地将其投入生产。
此外,我认为更好的解决方案将涉及CefSharp方面的代码更改。它们可以注册派生自
DynamicObject
并启用覆盖上的现有对象
window
(如
frameElement框架元素
). 据我所知,自
this question
.