重写CefApp.GetRenderProcessHandler()以便将JS转换为C#调用后,WPF应用程序崩溃

时间:2016-08-26 05:53:06

标签: javascript c# .net wpf cefglue

我正在使用Xilium.CefGlue和Xilium.CefGlue.WPF开发一个wpf应用程序。在SampleCefApp中实现Xilium.CefGlue.CefApp.GetRenderProcessHandler()后,我的WPF应用程序崩溃了。在此实现之前,应用程序正常工作,没有任何崩溃。其实我需要通过javascript函数从html本地页面调用一个C#函数。此功能在32位版本中正常工作,但在64位时不能正常工作。以下是我的实施。

internal sealed class SampleCefApp : CefApp
{
    public SampleCefApp()
    {

    }
    private CefRenderProcessHandler renderProcessHandler = new Views.DemoRenderProcessHandler();
    protected override CefRenderProcessHandler GetRenderProcessHandler()
    {
        return renderProcessHandler;
    }
}

以下消息显示应用崩溃

<ProblemSignatures>

    <EventType>APPCRASH</EventType>
    <Parameter0>StreetMap.vshost.exe</Parameter0>
    <Parameter1>14.0.23107.0</Parameter1>
    <Parameter2>559b788a</Parameter2>
    <Parameter3>libcef.DLL</Parameter3>
    <Parameter4>3.2743.1449.0</Parameter4>
    <Parameter5>57bbfe66</Parameter5>
    <Parameter6>80000003</Parameter6>
    <Parameter7>0000000000b68267</Parameter7>

</ProblemSignatures>

使用64位时,libcef dll是否存在任何问题。有没有人可以通过使用Xilium.CefGlue和Xilium.CefGlue.WPF来帮助实现JS到C#调用。 我从链接中使用以下参考代码 https://groups.google.com/forum/#!topic/cefglue/EhskGZ9OndY

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System;
namespace Xilium.CefGlue.Client {
    internal sealed class DemoApp: CefApp {
        private CefRenderProcessHandler renderProcessHandler = new DemoRenderProcessHandler();

        protected override CefRenderProcessHandler GetRenderProcessHandler() {
            return renderProcessHandler;
        }
    }

    internal class DemoRenderProcessHandler: CefRenderProcessHandler {
        MyCustomCefV8Handler myCefV8Handler = new MyCustomCefV8Handler();

        protected override void OnWebKitInitialized() {
            base.OnWebKitInitialized();

            var nativeFunction = @ "nativeImplementation = function(onSuccess) {
            native

            function MyNativeFunction(onSuccess);
            return MyNativeFunction(onSuccess);
        };
        ";

        CefRuntime.RegisterExtension("myExtension", nativeFunction, myCefV8Handler);
    }

    internal class MyCustomCefV8Handler: CefV8Handler {
        protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue,

            out string exception) {
            //Debugger.Launch();

            var context = CefV8Context.GetCurrentContext();
            var taskRunner = CefTaskRunner.GetForCurrentThread();
            var callback = arguments[0];
            new Thread(() => {
                //Sleep a bit: to test whether the app remains responsive
                Thread.Sleep(3000);

                taskRunner.PostTask(new CefCallbackTask(context, callback));

            }).Start();

            returnValue = CefV8Value.CreateBool(true);
            exception = null;
            return true;
        }
    }

    internal class CefCallbackTask: CefTask {
        private readonly CefV8Context context;

        private readonly CefV8Value callback;
        public CefCallbackTask(CefV8Context context, CefV8Value callback) {
            this.context = context;
            this.callback = callback;
        }

        protected override void Execute() {
            var callbackArguments = CreateCallbackArguments();

            callback.ExecuteFunctionWithContext(context, null, callbackArguments);
        }

        private CefV8Value[] CreateCallbackArguments() {
            var imageInBase64EncodedString = LoadImage(@ "C:\hamb.jpg");
            context.Enter();
            var imageV8String = CefV8Value.CreateString(imageInBase64EncodedString);
            var featureV8Object = CefV8Value.CreateObject(null);
            var listOfFeaturesV8Array = CefV8Value.CreateArray(1);

            featureV8Object.SetValue("name", CefV8Value.CreateString("V8"), CefV8PropertyAttribute.None);
            featureV8Object.SetValue("isEnabled", CefV8Value.CreateInt(0), CefV8PropertyAttribute.None);
            featureV8Object.SetValue("isFromJSCode", CefV8Value.CreateBool(false), CefV8PropertyAttribute.None);

            listOfFeaturesV8Array.SetValue(0, featureV8Object);
            context.Exit();

            return new [] {
                listOfFeaturesV8Array,
                imageV8String
            };
        }

        private string LoadImage(string fileName) {
            using(var memoryStream = new MemoryStream()) {
                var image = Bitmap.FromFile(fileName);

                image.Save(memoryStream, ImageFormat.Png);

                byte[] imageBytes = memoryStream.ToArray();

                return Convert.ToBase64String(imageBytes);
            }
        }
    }
}

我在第一时间加载的 HTML 文件:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>C# and JS experiments</title>
        <script src="index.js"></script>
    </head>
    <body>
        <h1>C# and JS are best friends</h1>
        <div id="features"></div>      
        <div id="image"></div>
    </body>
</html>

JavaScript 代码:

function Browser() {

}

Browser.prototype.ListAllFeatures = function(onSuccess) {
    return nativeImplementation(onSuccess);
}

function App(browser) {
    this.browser = browser;
}

App.prototype.Run = function() {
    var beforeRun = new Date().getTime();
    this.browser.ListAllFeatures(function(features, imageInBase64EncodedString) {
        var feautersListString = '';

        for (var i = 0; i < features.length; i++) {
            var f = features[i];

            feautersListString += ('<p>' + 'Name: ' + f.name + ', is enabled: ' + f.isEnabled + ', is called from js code: ' + f.isFromJSCode + '</p>');

        }

        feautersListString += '<p> The image: </p>';
        feautersListString += '<p>' + imageInBase64EncodedString + '</p>';
        document.getElementById("features").innerHTML = feautersListString;

        var afterRun = new Date().getTime();

        document.getElementById("image").innerHTML = '<img src="data:image/png;base64,' + imageInBase64EncodedString + '" />';

        var afterLoadedImage = new Date().getTime();
        console.log("ELAPSED TIME - INSIDE LIST ALL FEATURES: " + (afterRun - beforeRun));
        console.log("ELAPSED TIME - IMAGE IS LOADED TO THE <img> TAG: " + (afterLoadedImage - beforeRun));
    });
}

window.onload = function() {
    var browser = new Browser();
    var application = new App(browser);
    //Lets measure
    var beforeRun = new Date().getTime();

    application.Run();

    var afterRun = new Date().getTime();

    console.log("ELAPSED TIME - INSIDE ONLOAD: " + (afterRun - beforeRun));
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我启用了cef日志记录。它显示以下日志 [0826/171951:错误:proxy_service_factory.cc(128)]无法在单进程模式下使用V8代理解析程序。 。所以我在CeffSetting中更改了SingleProcess = false。现在崩溃问题已解决,然后请求的网页未显示在cefwpfbrowser中。 现在我从日志文件中收到以下消息 [0826/173636:VERBOSE1:pref_proxy_config_tracker_impl.cc(151)] 000000001B2A7CC0:将chrome proxy config service设置为000000001B234F60 [0826/173636:VERBOSE1:pref_proxy_config_tracker_impl.cc(276)] 000000001B2A7CC0:完成将代理推送到UpdateProxyConfig [0826/173637:VERBOSE1:webrtc_internals.cc(85)]无法获取下载目录。 如何在cefwpfbrowser中解决请求的页面未加载问题。