將瀏覽器嵌入 .NET 應(yīng)用程序中:DotNetBrowser 還是 CefSharp?
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
為 WPF 或 WinForms 應(yīng)用程序選擇瀏覽器組件,對(duì)于那些搜索基于Chrome的解決方案的人來說,DotNetBrowser[1]和CefSharp[2]是最明顯的選擇。 本文是我們的客戶在考慮其項(xiàng)目的開源庫和商業(yè)庫時(shí)提出的最常見比較點(diǎn)的匯編。 引擎CefSharp 實(shí)際上是 Chromium Embedded Framework[3] (CEF) 的 .NET 包裝器。包裝通過 C++/CLI 完成。 DotNetBrowser 在底層不使用 CEF 或 C++/CLI。相反,它采用了自己的方法直接與 Chromium 集成。它啟動(dòng)一個(gè)功能齊全的 Chromium 引擎,并通過進(jìn)程間通信 (IPC) 與其進(jìn)行通信。 架構(gòu)在 CefSharp 中,Chromium 引擎直接在您的 .NET 進(jìn)程中初始化[4]。初始化和關(guān)閉都必須在主應(yīng)用程序線程(通常是 UI 線程)中執(zhí)行。在不同的線程中調(diào)用它們通常會(huì)導(dǎo)致凍結(jié)。 此外,每個(gè)進(jìn)程可以執(zhí)行一次初始化和關(guān)閉。這個(gè)限制來自 CEF 本身,在執(zhí)行關(guān)閉后嘗試重新初始化 CefSharp 將導(dǎo)致錯(cuò)誤。 在 DotNetBrowser 中,Chromium 引擎在單獨(dú)的本機(jī)進(jìn)程中進(jìn)行初始化。不需要在主 UI 線程上執(zhí)行此操作——即使在工作線程中也可以執(zhí)行此操作。 您可以同時(shí)初始化和使用具有不同配置的多個(gè) Chromium 引擎,這在 CefSharp 中是不可能的。您可以在不再需要 Chromium 時(shí)將其關(guān)閉并隨時(shí)重新初始化。 穩(wěn)定性和內(nèi)存使用在單獨(dú)的進(jìn)程中運(yùn)行 Chromium 有更多優(yōu)點(diǎn):
對(duì)于 DotNetBrowser,Chromium 內(nèi)部的錯(cuò)誤不會(huì)導(dǎo)致 .NET 應(yīng)用程序崩潰。此外,甚至可以在托管代碼中正確檢測和處理這一切。例如,如果發(fā)生這種情況,那么您可以重新初始化 Chromium 并恢復(fù)用戶會(huì)話。 應(yīng)用程序域由于其架構(gòu),CefSharp 不能在非默認(rèn) AppDomain 中使用[5]。因此,它不能用于通過 VSTO 插件或 Excel-DNA 將 Chromium 嵌入到 Office 應(yīng)用程序中。Office VSTO 將加載項(xiàng)加載到單獨(dú)的 AppDomain 中[6]以進(jìn)行隔離。 DotNetBrowser 在非默認(rèn) AppDomain 中運(yùn)行。事實(shí)上,可以在不同的 AppDomain 中創(chuàng)建多個(gè) Chromium 引擎并同時(shí)使用它們。因此,DotNetBrowser 可用于創(chuàng)建 VSTO 加載項(xiàng)。 AnyCPU在針對(duì) AnyCPU 的應(yīng)用程序中使用 CefSharp 時(shí),您會(huì)發(fā)現(xiàn)它在這些應(yīng)用程序的 64 位環(huán)境中無法正常工作。 這兒有幾個(gè)選項(xiàng)[7]可以解決這個(gè)問題。其中之一是讓您的應(yīng)用程序始終在 32 位模式下運(yùn)行,另一個(gè)更復(fù)雜,需要修改項(xiàng)目文件(.csproj 或 .vbproj)和代碼。 在 DotNetBrowser 中,AnyCPU 支持開箱即用。因此,不需要類似的調(diào)整。 H.264, AAC視頻和音頻通常使用專有編解碼器進(jìn)行編碼,例如 H.264 和 AAC。此媒體無法在 CefSharp 中播放。 要在 CefSharp 中啟用這些編解碼器,您需要在啟用專有編解碼器的情況下自行重建 CEF。這是一項(xiàng)相當(dāng)復(fù)雜的任務(wù),可能需要長達(dá)一個(gè)月的時(shí)間[8]。 在 DotNetBrowser 中默認(rèn)禁用專有編解碼器??梢酝ㄟ^編程方式啟用它們,而無需重建庫。 安全Chromium 通過利用操作系統(tǒng)為它們提供的安全性來限制其渲染器和實(shí)用程序進(jìn)程。此功能稱為 Chromium沙箱[9]。其主要目的是防止第三方代碼對(duì)計(jì)算機(jī)進(jìn)行持久更改或訪問機(jī)密信息。 CefSharp 不支持 Chromium 沙箱[10]。這個(gè)限制來自 CEF 本身,DotNetBrowser 支持沙箱并默認(rèn)啟用。如有必要,可以在初始化期間將其禁用[11]。 CefSharp 在 .NET 進(jìn)程中啟動(dòng) Chromium。這使您的應(yīng)用程序容易受到 CEF 和 Chromium 中的漏洞的影響。如果惡意軟件獲得了對(duì) Chromium 內(nèi)存的訪問權(quán),它也會(huì)獲得對(duì) .NET 內(nèi)存的訪問權(quán)。DotNetBrowser 在單獨(dú)的進(jìn)程中啟動(dòng) Chromium。Chromium 漏洞保留在 Chromium 中。 Visual Studio設(shè)計(jì)器現(xiàn)代 WPF 和 Windows 窗體應(yīng)用程序通常是在設(shè)計(jì)器的幫助下在 Visual Studio 中創(chuàng)建的。這種方法總體上簡化了 UI 創(chuàng)建并節(jié)省了大量時(shí)間和精力。 CefSharp 提供有限的設(shè)計(jì)器支持[12]。如果應(yīng)用程序本身以 x86 為目標(biāo),則其控件將在設(shè)計(jì)器中正確處理。AnyCPU 可能會(huì)工作,但尚未經(jīng)過徹底測試。 DotNetBrowser 控件是純 UI 控件,它們?cè)诖a中顯式初始化。您可以在設(shè)計(jì)器中不受任何限制地使用它們。安裝 NuGet 包或 VSIX 擴(kuò)展后,BrowserView 控件出現(xiàn)在工具箱中。它可以像任何其他常規(guī) UI 控件一樣被拖到窗體或窗口上。 嵌入應(yīng)用程序 UICefSharp 提供 WPF 和 Windows 窗體支持。但是,它的 WPF 實(shí)現(xiàn)只能在 離屏渲染模式[13] 下工作。此實(shí)現(xiàn)具有有限的觸摸屏和IME[14]支持。 DotNetBrowser 在兩種渲染模式下同時(shí)支持 WPF 和 Windows 窗體。在硬件加速模式下,觸摸、手勢和 IME 由 Chromium 自行處理,因此它們開箱即用。在離屏模式下,存在一些已知的限制[15]。 以下是將 CefSharp 嵌入 WPF 窗口的方法: 就是這樣,在最簡單的情況下,不再需要編寫代碼。但是,在這種情況下,CefSharp 初始化和關(guān)閉是隱式執(zhí)行的,很難確定它是否已經(jīng)在某個(gè)點(diǎn)初始化。 將 DotNetBrowser 嵌入 WPF 窗口的過程需要額外的步驟。例如: MainWindow.xaml MainWindow.xaml.cs 在這里,大部分代碼都與 Chromium 實(shí)例和 IBrowser 實(shí)例的顯式初始化和關(guān)閉有關(guān)。UI 控件初始化是通過調(diào)用 Initializefrom() 顯式執(zhí)行的。這種方法可以更好地控制初始化和關(guān)閉過程,并且更容易自定義初始 Chromium 配置。 高DPI在 CefSharp 中,瀏覽器子進(jìn)程的默認(rèn) DPI 感知[16]是 Per-Monitor。因此,桌面應(yīng)用程序應(yīng)具備DPI 感知功能[17],才能在高 DPI 顯示器(DPI 比例設(shè)置大于 100% 的顯示器)上正確運(yùn)行。在其他情況下,瀏覽器內(nèi)容可能無法正確呈現(xiàn),例如: DotNetBrowser 以不同的方式支持高 DPI。在初始化過程中,它會(huì)檢查當(dāng)前進(jìn)程的 DPI 感知,并為相應(yīng)的 Chromium 引擎設(shè)置匹配的 DPI 感知。因此,無需讓您的應(yīng)用程序顯式識(shí)別 DPI 以避免在高 DPI 顯示上呈現(xiàn)偽影。 無頭DotNetBrowser 和 CefSharp 都可以在沒有 UI 的應(yīng)用程序中使用。 在 CefSharp 中,CefSharp.OffScreen.Chromium WebBrowser 用于此目的。初始化過程通常保持不變。但是,如果您的代碼使用 async/await 模式,則需要使用同步上下文來確保在主線程上而不是在不同的工作線程上執(zhí)行初始化和關(guān)閉。 要在沒有 UI 的應(yīng)用程序中使用 DotNetBrowser,您需要像往常一樣執(zhí)行初始化。在這種情況下,沒有需要初始化的 BrowserView。即使您的代碼使用async/await模式,也無需創(chuàng)建和使用同步上下文。 API和功能這兩種產(chǎn)品都有許多可用的功能。在本文中,我將比較幾個(gè)最重要的,以展示 API 的不同之處。 DOM訪問在 CefSharp 中,您只能通過執(zhí)行 Javascript 調(diào)用來訪問 DOM。例如: DotNetBrowser 提供了豐富的 DOM API,可用于直接從 .NET 執(zhí)行以下操作:
例如,以下是如何在 DotNetBrowser 中的網(wǎng)頁上執(zhí)行相同的操作: 因此,在 DotNetBrowser 中與網(wǎng)頁執(zhí)行復(fù)雜的交互要方便得多。無需編寫難以調(diào)試和支持的復(fù)雜 Javascript 代碼。 DotNetBrowser 中的 DOM API 不是一組 Javascript 調(diào)用的包裝器。它直接對(duì) Blink 引擎進(jìn)行 IPC 調(diào)用。 與Javascript交互執(zhí)行Javascript并處理結(jié)果CefSharp 和 DotNetBrowser 都提供了在網(wǎng)頁上執(zhí)行 Javascript 的能力。 在 CefSharp 中,有兩種方法可用于此目的,executeJavascriptAsync 和 EvaluatescriptAsync。兩者都可用于瀏覽器本身(通過擴(kuò)展方法)或其中的一個(gè)框架: 然后使用 JavascriptResponse.Result 獲取執(zhí)行結(jié)果。 可能的結(jié)果類型有 bool, int, long, double, string, List, IDictionary<string, object>, 和 IJavascriptCallback。這里的集合是 Javascript 集合的快照表示,而 IJavascriptCallback 是一種 Javascript 函數(shù)表示,可用于從 .NET 端執(zhí)行它。 在 DotNetBrowser 中,有 IFrame.executeJavascript() 用于此目的。此方法的通用版本可用于顯式指定預(yù)期的返回類型: 這里的主要區(qū)別是可以將 Javascript 對(duì)象表示為IJsObject。使用此接口,您可以訪問和修改 Javascript 對(duì)象的屬性并調(diào)用其方法。在 .NET 端對(duì) IJsObject 所做的所有更改都將立即反映在 Javascript 端。此外, executeJavascript 調(diào)用可以返回一個(gè) IElement,這是一個(gè) DOM 元素的表示,您可以使用它來訪問和修改 DOM 屬性或訂閱 DOM 事件。 從Javascript調(diào)用.NETCefSharp 和 DotNetBrowser 都可以使網(wǎng)頁上的 Javascript 可以訪問 .NET 對(duì)象,但是,CefSharp 存在一些特定的限制。 CefSharp Javascript 綁定可用于 Javascript 和 .NET 之間的通信 但是,CefSharp 不允許[18]將Form, Window 或任何Control注入 Javascript。另外,CefSharp 只支持調(diào)用注入對(duì)象的方法。如果需要設(shè)置屬性,則必須修改類并創(chuàng)建 Get/Set 方法。 在 DotNetBrowser 中,您可以將任何對(duì)象注入 Javascript,包括 Form, Window 和 Control 對(duì)象。執(zhí)行注入后,您可以訪問注入的 .NET 對(duì)象的公共字段、屬性和方法。此外,DotNetBrowser 支持從 Javascript 訪問索引屬性(使用字符串或數(shù)字索引器)。如果您需要從 Javascript 訪問 .NET 集合,這會(huì)很有幫助。 截屏兩種解決方案都支持在瀏覽器不可見時(shí)進(jìn)行截屏。但是,API 有明顯不同。以下是代碼片段: Taking a screenshot in CefSharp Taking a screenshot in DotNetBrowser 主要的 DotNetBrowser DLL 不使用 System.Drawing 中的類型,因?yàn)樗南拗?/span>[19],因此,它提供了自己的類型。然后可以通過 DotNetBrowser.Wpf 或 DotNetBrowser.WinForms 中提供的擴(kuò)展方法將此類型轉(zhuǎn)換為常規(guī) System.Drawing.Bitmap。 分發(fā)和部署CefSharp 需要 Microsoft Visual C++ 運(yùn)行時(shí)存在于環(huán)境中[20]。Visual C++ 2015 是最低版本,但所需的確切版本取決于 Chromium 版本。因此,需要在您希望運(yùn)行基于 CefSharp 的應(yīng)用程序的每臺(tái)機(jī)器上預(yù)安裝 Microsoft Visual C++ Redistributable Package,將其設(shè)置為安裝程序的依賴項(xiàng),或?qū)⑵?DLL 打包為應(yīng)用程序的一部分,并確保 CefSharp 正確找到它們。 在 DotNetBrowser 中,所有必需的 Chromium 二進(jìn)制文件和 DLL 都已打包到 DotNetBrowser DLL 中,并且可以在執(zhí)行期間自動(dòng)提取。您無需預(yù)先安裝 Microsoft Visual C++ Runtime 即可使用 DotNetBrowser。 支持和更新CefSharp 是一個(gè)開源項(xiàng)目。如果您發(fā)現(xiàn)錯(cuò)誤或缺少功能,您可以提出建議[21]。 DotNetBrowser是為使用.NET開發(fā)軟件的商業(yè)公司設(shè)計(jì)和創(chuàng)建的商業(yè)產(chǎn)品,對(duì)集成第三方解決方案的質(zhì)量和支持有很高的要求。自 2015 年以來,TeamDev 開發(fā)并支持 DotNetBrowser。 我們所有已訂閱有效標(biāo)準(zhǔn)支持[22]的客戶都可免費(fèi)使用所有DotNetBrowser 新版本并獲得技術(shù)支持。如果您發(fā)現(xiàn)錯(cuò)誤或缺少功能,我們將應(yīng)用修復(fù)程序,實(shí)施所需功能,并根據(jù)任務(wù)的復(fù)雜性在幾天或幾周內(nèi)為您提供新版本的庫。 幾乎每個(gè)月都會(huì)發(fā)布一個(gè)新版本的 DotNetBrowser。我們會(huì)在 Chromium 正式發(fā)布后的 3-4 周內(nèi)將 Chromium 升級(jí)到最新的穩(wěn)定版本(帶有最新的安全補(bǔ)丁和修復(fù)的漏洞)。 概括因?yàn)殚_源和免費(fèi),CefSharp 被廣泛使用。它很容易為基本案例進(jìn)行配置,并且擁有廣泛的文檔和活躍的開源開發(fā)者社區(qū)。 但是,它具有來自其設(shè)計(jì)和架構(gòu)的限制。缺少沙盒支持使其安全性降低,并且進(jìn)程內(nèi)方法會(huì)影響穩(wěn)定性并增加應(yīng)用程序的內(nèi)存使用量。 它也不能用于暗示在單獨(dú)的 AppDomain(如 VSTO)中運(yùn)行代碼的環(huán)境。對(duì)于其他一些情況,例如播放使用專有編解碼器編碼的內(nèi)容,您必須自己構(gòu)建、更新和維護(hù) CEF。這需要大量額外的工作和基礎(chǔ)設(shè)施。 與加載的網(wǎng)頁的復(fù)雜交互會(huì)通過 Javascript 注入執(zhí)行,這使得生成的代碼更難調(diào)試和支持。 DotNetBrowser 簡化了所有這些案例的開發(fā)過程——由于它的進(jìn)程外架構(gòu),它可以用于創(chuàng)建更穩(wěn)定和安全的解決方案。使用 DotNetBrowser,您可以與需要在單獨(dú)的 AppDomain 中運(yùn)行代碼的應(yīng)用程序集成,并在網(wǎng)頁上執(zhí)行復(fù)雜的操作,而無需進(jìn)行大量的 Javascript 注入。 參考資料[1] DotNetBrowser: https://teamdev.com/dotnetbrowser/?utm_campaign=dotnetbrowser-articles&utm_medium=article&utm_source=medium [2] CefSharp: http://cefsharp.github.io/ [3] Chromium Embedded Framework: https://bitbucket.org/chromiumembedded/cef/src/master/ [4] 引擎直接在您的 .NET 進(jìn)程中初始化: https://github.com/cefsharp/CefSharp/wiki/General-Usage [5] CefSharp 不能在非默認(rèn) AppDomain 中使用: https://github.com/cefsharp/CefSharp/wiki/General-Usage [6] 將加載項(xiàng)加載到單獨(dú)的 AppDomain 中: https://learn.microsoft.com/en-us/visualstudio/vsto/architecture-of-vsto-add-ins?view=vs-2022 [7] 幾個(gè)選項(xiàng): https://github.com/cefsharp/CefSharp/issues/1714 [8] 可能需要長達(dá)一個(gè)月的時(shí)間: https://greenlightstudionet.wordpress.com/2019/10/09/stream-netflix-in-your-c-sharp-program/ [9] Chromium沙箱: https://www.google.com/googlebooks/chrome/med_26.html [10] 不支持 Chromium 沙箱: https://github.com/cefsharp/CefSharp/wiki/General-Usage [11] 在初始化期間將其禁用: https://dotnetbrowser-support.teamdev.com/docs/guides/gs/chromium.html [12] 提供有限的設(shè)計(jì)器支持: https://github.com/cefsharp/CefSharp/wiki/General-Usage [13] 離屏渲染模式: https://github.com/cefsharp/CefSharp/wiki/General-Usage [14] IME : https://github.com/cefsharp/CefSharp/issues/1262 [15] 已知的限制: https://dotnetbrowser-support.teamdev.com/docs/guides/gs/browser-view.html [16] 默認(rèn) DPI 感知: https://github.com/cefsharp/CefSharp/wiki/General-Usage [17] DPI 感知功能: https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windowse [18] 不允許: https://github.com/cefsharp/CefSharp/wiki/General-Usage [19] 因?yàn)樗南拗? https://learn.microsoft.com/en-us/dotnet/api/system.drawing?view=netstandard-2.0 [20] 需要 Microsoft Visual C++ 運(yùn)行時(shí)存在于環(huán)境中: https://github.com/cefsharp/CefSharp/wiki/Output-files-description-table-%28Redistribution%29 [21] 提出建議: https://github.com/cefsharp/CefSharp [22] 標(biāo)準(zhǔn)支持: https://dotnetbrowser-support.teamdev.com/getting-help/ [23] 聯(lián)系并獲得幫助: https://dotnetbrowser-support.teamdev.com/getting-help/?utm_campaign=dotnetbrowser-articles&utm_medium=article&utm_source=medium 該文章在 2023/7/4 11:02:24 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |