關於CefSharp的坎坷之路

 

項目背景:html

公司的XX產品須要升級和之後支持多平臺的使用。由於以前項目是由WPF實現的。目前之後想做爲Html5來展現頁面。web

由於涉及到總體更改遇到的問題較多以及其餘緣由,因此只是內部內容區域先替換爲Html5頁面,因此須要嵌入Browser控件。canvas

Browser控件的選型:windows

1.Winform中的WebBrowser瀏覽器

2.WPF中的WebBrowser安全

3.WebKit.Net服務器

4.CefSharpapp

5.awesominum框架

6.OpenWebKitSharpide

7. geckofx

通過初步查閱,WebKit.Net、OpenWebKitSharp 和geckofx 都是基於Winform的。CefSharp 在GitHub有源碼,而且具有Winform和WPF的版本。awesominum能夠容許把網頁嵌入到 3D 畫面或遊戲中,支持unity3D。

通過嘗試.Net中的Winform版本的WebBrowser,背景沒法直接設置透明, 須要經過Windows Api進行處理(僅查閱,未實際進行處理和驗證)。

首先把Winform的WebBrowser放到項目中進行了實驗和處理,發現兩個致命問題:一個是背景不透明,由於整個背景具備漸變和過渡效果。第二個是,頁面切換具備滑動過渡效果。

Winform版的WebBrowser會懸浮最上層,不會漸變隱藏消失。  基於以上兩點,針對Winform和基於Winform的其餘暫時不在考慮。

(調研其餘基於Winform的第三方控件沒有具體查看是否內部已經處理這些問題,喜歡深刻研究的同窗或使用過的同窗也能夠告訴我啊)

目前 調研CefSharp和Awesominum。

CefSharp的源碼Demo進行測試,目前是符合需求。Awesominum初步查看也符合需求。

特定需求:在某個Html5頁面中 須要調用攝像頭進行錄像拍攝。

現象:在CefSharp的初步顯示具有攝像頭打開的頁面時,沒法打開攝像頭。開始查找問題,最後發現 要給CefSharp的CommandLineArgs添加一些命令才能夠顯示處理,而且要啓動WebServer服務。(後面會詳細講解此問題)

而在Awesominum中未找到能夠添加命令行參數的方法,因此姑且放棄。最好仍是先選用CefSharp。

目前,引用CefSharp,我是經過Nuget進行獲取安裝的。

關於Nuget的使用,你們能夠自行搜索使用。Nuget還能夠本身搭建公司專屬的插件服務器和客戶端調用。

其中須要注意的是:

1.使用正確的Package source資源地址進行搜索下載。

以下圖,在搜搜CefSharp的時候,要使用nuget.org地址或All下載資源,這樣才能搜索到CefSharp,Microsoft Visual Studio Offline Packages 則是針對微軟的一些插件和應用包。

2.插件的安裝和卸載都要要用Nuget進行處理

在使用過程當中,有時候會遇到解決方案打開,而後操做生成項目時,提示正在恢復還原Nuget包,而後,而後,就一直而後了... 那叫個等的花都謝了。強制關閉,下次仍是會有滴。仍是放棄抵抗吧。

若是Nuget的包恢復和還原出來錯活着不須要了,仍是經過Nuget進行卸載,以避免有殘留。真是不使用不知道,一使用全亂套,啊哈哈~~~~

純屬我的體會,箇中滋味,各自體會。

----------------如下爲使用CefSharp過程當中,我的遇到的一些問題和注意事項------------------------

一:引用CefSharp的編譯須要指定目標平臺X86或X64

    在咱們解決方案中,通常默認都是AnyCup的,因此在生成時會提示錯誤。

由於CefSharp的使用須要明確目標平臺的。因此生成時,要指定是x86仍是x64,由於咱們項目須要 要改成X86.  有的會問,我已經修改目標平臺爲x86了,以下圖 位置:一、2處。而編譯仍是生成不成功呢?這是爲何呢?爲何呢?

請不要在項目的屬性上進行設置。要在整個解決方案的配置上進行設置 引用CefSharp的項目的Platform 平臺。仔細看你會發現 解決方案的的項目的平臺以下圖 位置3處和 項目屬性中是不一致的呢。因此切記。

二:CefSharp中的生成目錄的問題

在咱們項目中,CefSharp的項目是做爲插件的方式嵌入主框架中的,因此生成目錄到了根目錄下的Plugins目錄下。運行後,你會發現一直提示沒法找到CefSharp.core.dll等相關的dll文件。  哈哈,找不到,找不到就對了。

CefSharp是到根目錄下(默認是指Bin)的環境中尋找dll的,因此沒法進行找到。暫時也未從源碼案例中找到進行設置目錄的方式(若其餘忍知曉能夠告知我哦)。

不過這樣也沒關係,不就是在程序的運行環境中找不到嗎?咱們本身添加上不就好了。代碼以下:

  var pluginsPath = Path.Combine(Environment.CurrentDirectory, "Plugins");
  var path = Environment.GetEnvironmentVariable("PATH") + ";" + pluginsPath;
  Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);

  在程序運行啓動時,把對應的環境變量路徑添加上Plugins的路徑。運行起來,你會發現能夠了。

三:關於CefSharp生成時產生的各類文件是否項目都必須用到的問題

    好比,生成的文件中有擴展名爲.pak的文件,pak文件是一種特殊的文件壓縮格式。 比較常應用於遊戲。 關於此類文件,在使用CefSharp也須要具有此類文件。 
網上搜索:將locales及其下全部都設置爲輸出,裏面有個en-US.pak文件,如沒有,則應用程序會啓動顯示錯誤退出。再將devtools_resources.pak 設置爲輸出,不然調用devtools時將報錯不能打開。(常見問題官網解釋)
經過在CefSharp的源碼中搜索也確實使用到了pak文件,因此此類文件也不可缺乏。

四:關於CefSharp顯示頁面一直閃爍的問題。

      具體查找過程就不詳述,只能一把鼻涕一把淚的說 那也是一個煎熬的過程,不能說問題有多大,只能說很小的問題,沒有找對方向。如今就把問題告訴你們。   

      通過和從GitHub下載的CefSharp3的源碼進行對比,最終發現,咱們未進行配置app.manifest文件的配置,大神們也許不少app.manifest文件的用途,而對於我這種不踩一兩次坑,不長教訓的,之前都會輕輕掠過這種東西。

      app.manifest的文件能夠經過添加文件來自動生成。也能夠從源碼中拷貝過來。而後在項目的屬性=》應用(Application)中進行Resources=》Manifest配置上。下面描述app.manifest的描述的功能。

     其中主要 代碼片斷入下:   

 1  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
 2     <application>
 3       <!-- A list of the Windows versions that this application has been tested on and is
 4            is designed to work with. Uncomment the appropriate elements and Windows will 
 5            automatically selected the most compatible environment. -->
 6 
 7       <!-- Windows Vista -->
 8       <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
 9 
10       <!-- Windows 7 -->
11       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
12 
13       <!-- Windows 8 -->
14       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
15 
16       <!-- Windows 8.1 -->
17       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
18 
19       <!-- Windows 10 -->
20       <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
21 
22     </application>
23   </compatibility>
24 
25   <!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
26        DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need 
27        to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should 
28        also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
29   
30   <application xmlns="urn:schemas-microsoft-com:asm.v3">
31     <windowsSettings>
32       <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
33     </windowsSettings>
34   </application>
app.manifest的主要代碼片斷  

 自動添加app.manifest時會有對每一個標籤的描述信息,根據描述信息能夠得知<dpiAware>true</dpiAware>實際上是設置適應高高dpi對程序的影響。目前不少電腦都是高dpi的。

    應該是 不一樣操做系統下,渲染機制是有區別的,因此爲了更好的適應高dpi和不一樣系統的影響,因此最好不一樣的系統能夠按照本身專屬的環境進行處理,而supportedOs標籤的設置解決了這類問題。

五:關於Windows8.1系統運行程序 頁面依舊閃爍的緣由。

在配置好app.manifest以後,覺得能夠源碼的解決了頁面閃爍的問題。然後,被告知Windows8.1的系統卻依舊閃爍。這下又懵逼了~~懵逼~~了~~~!!!

後來又仔細閱讀關於CefSharp中的代碼和各類配置,在源碼CefSharp3的命令行參數CefCommandLineArgs的配置中驚奇的發現了下面一段代碼:

1  var osVersion = Environment.OSVersion;
2             //Disable GPU for Windows 7   
3             if (osVersion.Version.Major == 6 && osVersion.Version.Minor == 1)
4             {
5                 // Disable GPU in WPF and Offscreen examples until #1634 has been resolved
6                 settings.CefCommandLineArgs.Add("disable-gpu", "1");
7             }
CefSharp禁用GPU的命令行參數

其中,Major和Minor分別指代系統的主版本(大版本)、次版本(小版本)版本號。其中指定了Windows7系統會禁用 GPU。,突發奇想,是否windows8.1也是由於這個問題?而後開始驗證。

因此,經查閱,各系統的對應版本以下:

系統的主版本、次版本

1 Windows 10 -- 10.0*
 2 Windows Server 2016 Technical Preview -- 10.0*
 3 Windows 8.1 -- 6.3*
 4 Windows Server 2012 R2 -- 6.3*
 5 Windows 8 -- 6.2
 6 Windows Server 2012 --6.2
 7 Windows 7 -- 6.1
 8 Windows Server 2008 R2 -- 6.1
 9 Windows Server 2008 -- 6
10 Windows Vista -- 6
11 Windows Server 2003 R2 -- 5.2
12 Windows Server 2003 -- 5.2
13 Windows XP 64-Bit Edition -- 5.2
14 Windows XP -- 5.1
15 Windows 2000 -- 5
系統的主版本、次版本

如上圖得知,若判斷是否爲Windows8.1系統,判斷osVersion.Version.Major == 6 && osVersion.Version.Minor == 3 便可,

可是不知源碼中 爲什麼要判斷windows7的禁用GPU,在windows7下取消禁用GPU的測試,發現頁面並未閃爍。

可是爲了安全起見,而且身邊沒有window8和其餘的系統,因此決定,應用CefSharp的時候,配置CefCommandLineArgs進行了只判斷osVersion.Version.Major == 6的處理,即windows8.一、windows八、windows7等都禁用了GPU。

暫且不知,這之後是否會成爲歷史遺留問題~~~~~嘻嘻~~。

六:關於  調試狀態運行程序不報錯,可是頁面卻一直未顯示的問題

              直接運行exe程序,提示找不到 CefSharp.BrowserSubprocess.exe和CefSharp.Core.dll等missing的問題。

     在操做cefsharp項目並拷貝文件到輸出目錄過程當中,會未對CefSharp.BrowserSubprocess.exe進行處理,致使CefSharp對應的運行環境下未有CefSharp.BrowserSubprocess.exe文件。

    而CefSharp的瀏覽器是須要依賴此文件的,因此,纔會出現頁面顯示不出畫面的問題。CefSharp.BrowserSubprocess.exe文件是安裝Nuget時自動下載下來的,可是在項目應用過程當中,並不會拷貝生成到特定的輸出目錄下,

    因此,想把此文件進行保存下載,上次到源碼管理中,生成的時候也自動複製到輸出目錄,以免丟失此文件而報錯的狀況。

處理方式:

在項目中添加了Files文件,並把CefSharp.BrowserSubprocess.exe 放入其中,設置屬性爲Content和Copy Always 

設置項目生成成功後的腳本,拷貝到運行環境目錄 便可。

七:關於使用CefSharp起用攝像頭的問題

     爲何要針對這個問題拿出來講一說你呢?可能會有人問:調用攝像頭不是js操做的問題嗎?跟CefSharp有什麼關係。          請往下看eb( ̄▽ ̄)d

     因項目要顯示的網頁中 有一個須要打開攝像頭拍照的功能,js的代碼以下:    

1  var mediaStream = null, track = null;
 2     var video;
 3     var n = 0;
 4     navigator.getMedia = (navigator.getUserMedia ||
 5         navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
 6         navigator.msGetUserMedia);
 7     if (navigator.getMedia) {
 8         navigator.getMedia(
 9             {
10                 video: true
11             },
12             // successCallback
13             function (stream) {
14                 var s = window.URL.createObjectURL(stream);
15                 video = document.getElementById('video');
16                 video.src = window.URL.createObjectURL(stream);
17                 mediaStream = stream;
18                 track = stream.getTracks()[0];
19                 $scope.photoBtnDiable = false; $scope.$apply();
20             },
21             // errorCallback
22             function (err) {
23                 $scope.errorPhoto();
24                 console.log("The following error occured:" + err);
25             });
26     } else {
27         $scope.errorPhoto();
28     }
29     //拍照
30     $scope.snap = function () {
31         var canvas1 = document.getElementById('canvas1');
32         var canvas2 = document.getElementById('canvas2');
33 
34         var ctx1 = canvas1.getContext('2d');
35         var ctx2 = canvas2.getContext('2d');
36 
37         ctx1.drawImage(video, 0, 0, canvas1.width, canvas1.height);
38         n++;
39         if (n % 2 == 0) {
40             ctx2.drawImage(video, 0, 0, canvas2.width, canvas2.height);
41         } else {
42             ctx1.drawImage(video, 0, 0, canvas1.width, canvas1.height);
43         }
44         //$uibModalInstance.close(canvas.toDataURL("image/png"));
45     };
46     //關閉攝像頭
47     $scope.closeCamera = function () {
48         if (mediaStream != null) {
49             if (mediaStream.stop) {
50                 mediaStream.stop();
51             }
52             $scope.videosrc = "";
53         }
54         if (track != null) {
55             if (track.stop) {
56                 track.stop();
57             }
58         }
59     }
JS調用攝像頭拍照代碼

    測試運行後發如今CefSharp使用,不起做用。由於咱們訪問頁面一開始是經過file:///url的方式進行本地訪問的。有經驗的朋友會發現,瀏覽器不少(好比調動攝像頭)的操做只支持安全源訪問,而且有的瀏覽器會提示是否容許啓動攝像頭。 

    爲了能使用攝像頭因此須要啓動web 服務,以http或者localhost的方式進行訪問。由於,經過HttpListener搭建了個Web 服務,而後測CefSharp3的頁面依舊不能夠調用攝像頭,通過經過其餘瀏覽器調用顯示沒有問題。

    這下又一頭霧水,通過查閱資料,滾滾洪水中找到了那一顆螺絲釘,又位使用過CefSharp的一位 博主的博客 的說明中提到了 CefSharp要進行參數配置的以下:

    在CefCommandLineArgs添加了enable-media-stream參數,意思是啓用媒體流

   //主要是配置開啓Media的命令參數,此配置能夠容許攝像頭打開攝像
            settings.CefCommandLineArgs.Add("enable-media-stream", "1");

    憶往昔歲月,已然猶記此些。

 

結後語:

     第一次認真編寫博客,排版等還有待完善。但願各位博友多鼓勵,多指教。

相關文章
相關標籤/搜索