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() + "\n"; //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:\Project\2013\CefSharpDemo\CefSharpDemo\發布\Application Files\CefSharpDemo_1_0_0_7\natives_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
    根據報錯加入locales\en-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參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM