• CefSharp的引用、配置、实例


    Winform下CefSharp的引用、配置、实例与报错排除

    本文详细介绍了CefSharp在vs2013、.net4.0环境下,创建Winfrom项目、引用CefSharp的方法,演示了winfrom下CefSharp的基本使用,包括显示网页url/本地html显示、JavaScript调用异步C#方法、JavaScript调用带参数C#方法、JavaScript调用委托C#方法、JavaScript调用C#返回实体对象、ChromiumWebBrowser控件扩展IContextMenuHandler接口实现禁用右击按钮菜单、简单介绍WebGL页面渲染;详细介绍了的CefSharp依赖项、常见报错查看与必要依赖项分析,最后进行了简单总结、并提供了源码的下载.

    [TOC]

    1、关于CefSharp

    装一手,比较简单的英语
    CefSharp lets you embed Chromium in .NET apps. It is a lightweight .NET wrapper around the Chromium Embedded Framework (CEF) by Marshall A. Greenblatt. About 30% of the bindings are written in C++/CLI with the majority of code here is C#. It can be used from C# or VB, or any other CLR language. CefSharp provides both WPF and WinForms web browser control implementations.

    CefSharp is BSD licensed, so it can be used in both proprietary and free/open source applications. For the full details, see the LICENSE file.

    自己总结的:
    CefShar是一个提供了Chromium Embedded Framework (CEF)的.NET接口的开源项目,提供了Winform、WPF封装,可以用来代替微软的WebBrowser,浏览网页,尤为强大的是实现了C#、VB等vs支持的语言与JavaScript的交互方法。

    2、CefSharp项目源码下载

    3、Winfrom项目引入CefSharp

    我的开发环境vs2013、.net4.0,Nugget中搜索CefSharp显示的版本是v53,然而v51.0.0-pre01的Breaking Changes里面有这么一句

    CefSharp requires at least .Net 4.5.2 (Last version to support .Net 4.0 is 49)

    不想安装.net4.5.2,所以只能通过工具-程序包管理器-程序包管理控制台手动命令行导入版本v49。0.1的,输入命令Install-Package CefSharp.WinForms -Version 49.0.1回车等待执行完成,我这里已经安装过了。

    其他版本命令请参考http://www.nuget.org/packages/CefSharp.WinForms.
    等待导入成功,生成一下...报错...

    CefSharp.Common does not work correctly on 'AnyCPU' platform. You need to specify platform (x86 / x64).

    嗯?!!!

    cefsharp不支持anycup,还需要设置一下目标平台为x86或x64

    如果你以为只是在项目名右击-属性-生成-目标平台改为x86就太天真了....
    反正我试了不行...
    正确的姿zhi势shi: 解决方案名右击-属性-配置属性-配置,右边平台选择x86或x64,什么?选不到?

    点击当前界面右上角配置管理器-活动解决方案平台下拉新建,x86/x64随便选,回来这边下拉已经可以选择了,完事左下角确定,再生成一下试试吧

    以上看不懂的参考这里.net使用cefsharp开源库开发chrome浏览器(二)

    4、Winfrom下CefSharp的基本使用

    4.1 显示一个页面

    4.1.1 显示url网页

    对照下面在一个Form的对应位置添加代码

           using CefSharp.WinForms;
           public partial class Form1 : Form
            {
                ChromiumWebBrowser webBrower = null;
                public Form1()
                {
                    InitializeComponent();
                    Load += Form_Load;
                }
                private void Form_Load(object sender, EventArgs e)
                {
                    string path = "www.baidu.com";                  
                    webBrower = new ChromiumWebBrowser(path);
                    webBrower.Dock = DockStyle.Fill;//填充方式
                    this.Controls.Add(webBrower);
                }
            }

    直接运行就OK了

    4.1.2显示一个本地html

    把path改为File协议就行,例如:显示程序下的文件夹html中的test.html

    //获取文件的物理路径
    string path = AppDomain.CurrentDomain.BaseDirectory + "\html\test.html";
    //转换为File协议路径
    path = "file://" + path.Replace("\", "/"); 

    如果实在不知道怎么写的话,建议直接用浏览器把html打开,地址栏里面显示的file://链接就是File协议路径

    需要在 test.html文件上右击-属性-复制到输出目录改为始终复制,这样调试时debug下面才会有这个文件

    推荐个CCS3动画的html,直接右击保存到本地就行了大风车CCS3动画,修改完成,同样运行就可以看到页面了,运行还是挺流畅的.

    4.2 JavaScript调用异步C#方法

    走弯路后的说明:BoundObject等这三个类以及里面的方法都是可以自己任意定义实现的,和普通的方法类没有太大区别,没有必要去源码中拷过来.

    从源码的CefSharp.Example中找到三个类BoundObject、SubBoundObject、ExceptionTestBoundObject的源码拷过来,记得对应着自己的项目把命名空间名改了。

    如果是.net4.0,TestCallback、TestCallbackException两个方法有提示async/await、Task.Run的报错,处理方式:

    • 直接升级到.NET Framework 4.5:从用户安装便捷性上讲,个人感觉完全没必要
    • 直接修改掉,因为这是测试的代码,可自己写不用Task.Run,详情请参阅CSDN论坛-Task.Factory.StartNew()和Task.Run()有什么区别、 CSDN论坛-task .run必须是 4.5框架,4.0里没有;如果是想在.net4.0下使用async/await还有别的方法-直接Nuget搜索安装Microsoft.Bcl.Async,如果搜索太慢或者搜索不到可以直接在nuget控制台执行Install-Package Microsoft.Bcl.Async.如果和我一样提示Nuget版本2.7太低、至少需要2.8的,需要卸载升级Nuget,步骤:
      • 卸载:打开VS-〉打开菜单“工具”-“扩展管理器”-〉选择“NuGet Package Manager”-〉点击“卸载”,然后会提示重启,不自动重启的话可以自己手动重启
      • 下载新版本nugethttps://dist.nuget.org/index.html,根据你的vs版本选择下载后缀是.vsix,直接安装就行,装完最好再重启一下vs.

    我这里选择不升级.net 4.5后面一种方法,同时安装Microsoft.Bcl.Async.

    这里实现的是一个延时回调的例子,即点一个按钮,调用绑定的C#方法在3秒后显示一条消息同时调用js方法立即显示一条消息。
    测试内容准备:

    • BoundObject中定义回调方法(可以自己定义一个空的BoundObject类,增加一下内容)
      public void TestCallback(IJavascriptCallback javascriptCallback)
      {
      //.net 4.0 的写法
      const int taskDelay = 3000;
      Task.Factory.StartNew(async () =>
      {
      Delay(taskDelay);
      using (javascriptCallback)
      {
      //var response = new CallbackResponseStruct("This callback from C# was delayed " + taskDelay + "ms");
      await javascriptCallback.ExecuteAsync(" 来自C#的返回值,在当前延迟" + taskDelay + "ms");
      }
      });
      /*
      //.net 4.5的写法
      const int taskDelay = 1500;
      Task.Run(async () =>
      {
      await Task.Delay(taskDelay);

                  using (javascriptCallback)
                  {
                      //NOTE: Classes are not supported, simple structs are
                      var response = new CallbackResponseStruct("This callback from C# was delayed " + taskDelay + "ms");
                      await javascriptCallback.ExecuteAsync(response);
                  }
              });
               */
          }
    • 在Form中给ChromiumWebBrowser增加绑定,第三个参数false忽略方法名大小写建议不要忘记,否则JS中掉用时方法名默认区分大小写
      webBrower.RegisterJsObject("bound", new BoundObject(),false);
    • 新建个html,body中录入一下内容

          <p> Javascript Callback Test </p>
      <script type="text/javascript">
          function callback(s) {
              var result = document.getElementById('show');
              result.innerText += "callback返回值:" + s.toString() + " 时间:" + Date();
          }
          function TestCallback() {
              //调用后台C#方法TestCallback,返回结果回调方法callback
              bound.TestCallback(callback);
              var result = document.getElementById('show');
              result.innerText = "方法返回  时间: " + Date() + "
      ";
              //window.location.assign("http://www.baidu.com");
          }
      </script> 
      <button onclick="TestCallback()">TestCallBakck</button>
      <br />
      <span id="show"></span> 

      可以运行一下了,点击一下TestCallBakck按钮,会首先显示一行内容与时间,3秒后显示第二行内容.

    4.3 JavaScript调用带参数C#方法

    准备内容:

    • BoundObject添加Repeat方法

              public string Repeat(string str, int n)
          {
              string result = String.Empty;
              for (int i = 0; i < n; i++)
              {
                  result += str;
              }
              return result;
          }
    • html内容

          <p>带参数调用C# repeat方法</p>
      <span id="content"></span> 
      <script type="text/javascript">
          var result = bound.Repeat("hello ", 6);
          document.getElementById("content").innerHTML = ""+result+"";
      </script> 

      执行结果

    4.4 JavaScript调用委托C#方法

    这里将一个方法ReturnJsonEmployeeList作为参数进行传递,并返回一个json数据进行解析展示

    • BoundObject中添加方法

          public string ReturnJsonEmployeeList()
      {
          return "{"employees":[{"firstName":"John", "lastName":"Doe"},{"firstName":"Anna", "lastName":"Smith"},{"firstName":"Peter", "lastName":"Jones"}]}";
      }
    • html内容

           <p> 委托C#方法-返回json字符串</p>
          <script type="text/javascript">
          function myfunc(fucPara) {
              return fucPara();
          }
          var res = myfunc(bound.ReturnJsonEmployeeList);
          document.write("委托输出结果:" + res + "<br>");
          var json = JSON.parse(res); //eval("'"+ res+"'");
          document.write("employees 数量:" + json.employees.length + "<br>");
          document.write("json.employees[0].lastName :" + json.employees[0].lastName);
      </script>

      运行结果:

      4.5 JavaScript调用C#返回实体对象

      准备内容
    • 新建类SubBoundObject,对照添加以下内容

                   public class SubBoundObject
          {
              public string SimpleProperty { get; set; }
              public SubBoundObject()
              {
                  SimpleProperty = "This is a very simple property.";
              }
              public string GetMyType()
              {
                  return "My Type is " + GetType();
              }
              public string EchoSimpleProperty()
              {
                  return SimpleProperty;
              }
          }
    • BoundObject中添加内容

              public SubBoundObject SubObject { get; set; }
       public SubBoundObject GetSubObject()
          {
              return SubObject;
          }
    • html中添加内容

           <p>返回实体对象</p>
      <script type="text/javascript">
          document.write("bound.GetSubObject().SimpleProperty : " + bound.GetSubObject().SimpleProperty);
      </script> 

      运行结果:

    4.6 ChromiumWebBrowser控件扩展IContextMenuHandler接口实现禁用右击按钮菜单

    禁用右击菜单需要创建一个类实现接口IContextMenuHandler,然后把这个类赋值给ChromiumWebBrowser的MenuHandler即可。这里创建类MenuHandler:

         internal class MenuHandler : IContextMenuHandler
         { 
            public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
            {
                model.Clear(); 
            }   
            public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
            {
                return false; 
            }   
            public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame)
            { 
            }   
            public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
            {
                return false; 
            }
         }

    配置到ChromiumWebBrowser:

    webBrower.MenuHandler = new Class.MenuHandler();

    这里只是禁用了菜单,也可以在相关事件里面增加内容,实现自定义右击菜单、不同页面的不同右击菜单.

    4.6 WebGL页面渲染

    WebGL(全写Web Graphics Library)是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。

    使用WebGL可以实现很炫的页面效果,以下这些实例都可以直接应用到一个引入了CefSharp的WinFrom桌面程序上面.
    9个令人震惊的WebGL示例
    20个使用WebGL和Three.js实现的网页场景

    5、依赖项

    5.1必需的运行环境

    CefSharp官方文件readme.txt中有以下要求:

    • 根据X86/X64安装对应的 Visual C++ Redistributable Packages for Visual Studio 2013
    • 安装.Net 4.0或者.Net 4.0 Client Profile
    • 必有的依赖项
      • libcef.dll (CEF code)
      • icudtl.dat (Unicode Support data)
      • CefSharp.Core.dll, CefSharp.dll,
        CefSharp.BrowserSubprocess.exe, CefSharp.BrowserSubProcess.Core.dll
    • 根据不同的开发平台CefSharp.WinForms.dll、CefSharp.Wpf.dll、CefSharp.OffScreen.dll至少有一个

    5.2依赖内容排错

    重要说明:不想看高(dan)达(dan)上(teng)分析的,请直接看5.3依赖列表
    因为我这是nuget引入的,debug/release生成的内容很多,直接运行也是成功的,因此我以发布为例,实际和debug/release下的调试是一样的。
    首先发布好的内容是这样的

    直接运行setup.exe会有很多报错,因为vs的发布过程中忽略很多依赖内容,下面介绍一下怎么一步步定位到缺少的依赖项:

    • 运行生成的exe,会报错这个

      遇到这个问题的肯定没好好看上边的内容,从源码或者debug/release下找到libcef.dll、icudtl.dat考到exe目录下这个错误就没有了
    • 运行exe会有新的问题,xxx已停止工作-点击关闭程序,注意目录下出现了一个debug.log,打开显示
      FATAL:v8_initializer.cc(155)] Failed to open V8 file 'D:Project2013CefSharpDemoCefSharpDemo发布Application FilesCefSharpDemo_1_0_0_7 atives_blob.bin' (reason: -4)

    说明缺少natives_blob.bin,同上边直接拷贝过来

    • 继续运行exe,form1出现了但是没有内容,这时候看log是没有新的报错的,但是请持续观察,报错需要等一会儿才会进来
      [1226/142128:WARNING:resource_bundle.cc(311)] locale_file_path.empty() for locale
      [1226/142128:ERROR:main_delegate.cc(724)] Could not load locale pak for en-US
      [1226/142128:ERROR:main_delegate.cc(731)] Could not load cef.pak
      [1226/142128:ERROR:main_delegate.cc(748)] Could not load cef_100_percent.pak
      [1226/142128:ERROR:main_delegate.cc(766)] Could not load cef_extensions.pak
      根据报错加入localesen-US.pak 、 cef.pak、cef_100_percent.pak、cef_extensions.pak
    • 继续运行exe,form1出现了但是没有内容,仔细研究日志
      [1226/142128:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/142129:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/142925:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/142926:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/143326:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/143327:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/143502:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      [1226/143503:ERROR:child_process_launcher.cc(443)] Failed to launch child process
      看懂了吗,没看懂?
      好吧,我也没看懂....只好把debug/release下的文件往这边粘贴然后试试,然后在粘了CefSharp.BrowserSubprocess.Core.dll CefSharp.BrowserSubprocess.exe两个之后奇迹发生了....抓紧把之前粘的全删了...
    • 现在已经正常了,但是、但是log里面还有报错

      [1226/145245:ERROR:gpu_child_thread.cc(260)] Exiting GPU process due to errors during initialization
      [1226/145245:ERROR:browser_gpu_channel_host_factory.cc(133)] Failed to launch GPU process.

      好了不废话了,经过我的九牛二虎之力,发现加入libEGL.dll、libGLESv2.dll、d3dcompiler_43.dll、d3dcompiler_47.dll就OK了

      5.3依赖文件列表

      总结一下,CefSharp必有的文件:
      ---locales
      | |--en-US.pak
      |--cef.pak
      |--cef_100_percent.pak
      |--cef_extensions.pak
      |--CefSharp.BrowserSubprocess.Core.dll
      |--CefSharp.BrowserSubprocess.exe
      |--CefSharp.Core.dll
      |--CefSharp.dll
      |--CefSharp.WinForms.dll
      |--d3dcompiler_43.dll
      |--d3dcompiler_47.dll
      |--icudtl.dat
      |--libcef.dll
      |--libEGL.dll
      |--libGLESv2.dll
      |--natives_blob.bin
      补充一下,运行环境vs2013、.NET4.0,Winfrom,CefSharp v40.0.1.

    6、总结

    根据今天初步的部署、测试,感觉CefSharp可以算是比较成熟的CEF的在.net下的实现了,JavaScript和C#的交互做的简单易用,感觉可以比较容易的将一个Web应用的资源经过一定的重新整合打造成为一个桌面程序.

    吐槽:一个字,因为从根本上是集成了一个chrome浏览器,所以以上简单的Demo的发布程序的x64、release版本就达到了99.5M,360压缩、7z格式压缩后30.6m,正式项目增加了代码、引入了其他的dll、资源文件等会更大;不知道有没有方法可以做精简

    以上均为个人看法,各路大神请指点

    7、源码下载与参考资料

    7.1提供了两个版本

        CefSharpDemo20161227 包含packages 157M
        CefSharpDemo20161227 不含packages 131K

    下载请去原文:http://huisky.com/blog/16122515111968

    7.2参考资料

  • 相关阅读:
    发现个atan2的正确使用方式
    Forward+ Shading架构
    fatal: unable to connect to gitee.com: gitee.com[0: 180.97.125.228]: errno=Unknown error 解决方案
    HDFS HA(高可用性)集群规划
    如何使用RTP引擎对语音编码进行转码
    关于 Angular 应用 tsconfig.json 中的 target 属性
    浅谈 Orbeon form builder 的权限控制
    关于 Angular 应用 tsconfig.json 中的 lib 属性
    orbeon form 通过 url 的方式同第三方应用集成的开发明细
    orbeon form 的配置介绍
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6239233.html
Copyright © 2020-2023  润新知