cefsharp 关于C# 调用JavaScript的一个坑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cefsharp 关于C# 调用JavaScript的一个坑相关的知识,希望对你有一定的参考价值。

之前开发的一个产品在上线后总有奇怪的BUG,经过一番调试后发现在使用CEF控件的

EvaluateScriptAsync

这个方法的时候,并不能保证成功.

经过一番查询,发现官方文档(https://github.com/cefsharp/CefSharp/wiki/General-Usage#devtools)有这么一段

2. How do you call a javascript method that returns a result?

If you need to evaluate code which returns a value, use the Task<JavascriptResponse> EvaluateScriptAsync(string script, TimeSpan? timeout) method. JavaScript code is executed asynchronously and as such uses the .Net Task class to return a response, which contains error message, result and a success (bool) flag.

// Get Document Height
var task = frame.EvaluateScriptAsync("(function() { var body = document.body, html = document.documentElement; return  Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); })();", null);

task.ContinueWith(t =>
{
    if (!t.IsFaulted)
    {
        var response = t.Result;
        EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message;
    }
}, TaskScheduler.FromCurrentSynchronizationContext());

For a more detailed example check out this Gist

Notes

  • Scripts are executed at the frame level, and every page has at least one frame (MainFrame)
  • Only trivial values can be returned (like int, bool, string etc) - not a complex (user-defined) type which you have defined yourself. This is because there is no (easy) way to expose a random JavaScript object to the .NET world, at least not today. However, one possible technique is to turn the JavaScript object you wish to return to your .NET code into a JSON string with the JavaScript JSON.toStringify() method and return that string to your .NET code. Then you can decode that string into a .NET object with something like JSON.NET. See this MSDN link for more information. (https://msdn.microsoft.com/en-us/library/ie/cc836459(v=vs.94).aspx)

可以用这种方式获取到JS的返回值:

1 task.ContinueWith(t =>
2 {
3     if (!t.IsFaulted)
4     {
5         var response = t.Result;
6         EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message;
7     }
8 }, TaskScheduler.FromCurrentSynchronizationContext());

于是利用这一点,做了个"流水ID"

每次调用的时候就+1,另一头代码执行完后,返回该ID,如果调用失败(或者返回的ID无法识别),则重新发起,如果另一头收到连续两次一样的ID,则不做处理(但还是要返回ID的.).

这样个方法也能用来解决某些丢包问题.

以上是关于cefsharp 关于C# 调用JavaScript的一个坑的主要内容,如果未能解决你的问题,请参考以下文章

[Winform]CefSharp ——js调用c#方法

[CefSharp] 如何在JavaScript中调用C#代码

wpf中js调用C#后台方法,使用框架CefSharp

CefSharp的引用配置实例

cefsharp停止request

CefSharp.wpf Web 浏览器导航事件 (C# .Net)