让 CefSharp.WinForms 应用程序同时支持32位(x86)和64位(x64)的解决方案
當(dāng)我們?yōu)榛?.NET Framework 的 WinForm 程序增加 CefSharp.WinForms 依賴后,可能會(huì)遇到以下報(bào)錯(cuò)信息:
CefSharp.Common is unable to proceeed as your current Platform is ‘AnyCPU’. To target AnyCPU please read https://github.com/cefsharp/CefSharp/issues/1714. Alternatively change your Platform to x86 or x64 and the relevant files will be copied automatically. For details on changing your projects Platform see https://docs.microsoft.com/en-gb/visualstudio/ide/how-to-configure-projects-to-target-platforms?view=vs-2017 CefSharpDemo
CefSharp.Common.targets我們可以通過(guò)“配置管理器”為項(xiàng)目設(shè)置具體的 x86 或 x64 目標(biāo)平臺(tái)來(lái)消除該報(bào)錯(cuò),同時(shí)我們也可以通過(guò)一些設(shè)置讓我們的程序同時(shí)支持 x86 和 x64 目標(biāo)平臺(tái)。本篇將簡(jiǎn)述如何為依賴來(lái) CefSharp.WinForms 的程序啟用 AnyCPU 支持。英文版的操作步驟可參見(jiàn):Feature Request – Add AnyCPU Support 。
為依賴 CefSharp 的程序增加 AnyCPU 支持
筆者新建了一個(gè)名為 CefSharpDemo 的 WinForm 項(xiàng)目,并通過(guò) NuGet 引入 CefSharp.WinForms 組件:
首先,在項(xiàng)目上點(diǎn)擊右鍵,選擇“卸載項(xiàng)目”,在項(xiàng)目卸載成功后,再次點(diǎn)擊右鍵,選擇“編輯項(xiàng)目文件”。之后會(huì)看到以下類似的窗體:
在第一個(gè)?PropertyGroup?標(biāo)簽里增加?<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>?代碼段:
修改完成之后,再次在項(xiàng)目文件上右擊,選擇“重新加載項(xiàng)目”。此番操作之后,項(xiàng)目的生成就不會(huì)報(bào)錯(cuò)了,可以發(fā)現(xiàn)在 bin 目錄中多出了名為 x86 和 x64 的兩個(gè)文件夾,分別對(duì)應(yīng) 32 位和 64 位的應(yīng)用程序。接下來(lái)我們需要在程序中根據(jù)運(yùn)行環(huán)境,動(dòng)態(tài)選擇要加載的文件。
CefSharp 依賴文件的動(dòng)態(tài)加載
我們可以通過(guò)?AppDomain.CurrentDomain.AssemblyResolve?事件將應(yīng)用程序所需的組件注冊(cè)進(jìn)來(lái)。以下代碼實(shí)現(xiàn)了該功能,并且根據(jù)是否 64 位進(jìn)程選擇具體加載哪個(gè)目錄中的程序集:
using CefSharp;using CefSharp.WinForms;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.Runtime.CompilerServices;using System.Threading.Tasks;using System.Windows.Forms;namespace CefSharpDemo{static class Program{/// <summary>/// 應(yīng)用程序的主入口點(diǎn)。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);AppDomain.CurrentDomain.AssemblyResolve += Resolver;LoadApp();}[MethodImpl(MethodImplOptions.NoInlining)]private static void LoadApp(){var settings = new CefSettings();// Set BrowserSubProcessPath based on app bitness at runtimesettings.BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,Environment.Is64BitProcess ? "x64" : "x86","CefSharp.BrowserSubprocess.exe");// Make sure you set performDependencyCheck falseCef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);var frmMain = new FrmMain();Application.Run(frmMain);}// Will attempt to load missing assembly from either x86 or x64 subdirprivate static Assembly Resolver(object sender, ResolveEventArgs args){if (args.Name.StartsWith("CefSharp")){string assemblyName = args.Name.Split(new[] { ',' }, 2)[0] + ".dll";string archSpecificPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,Environment.Is64BitProcess ? "x64" : "x86",assemblyName);return File.Exists(archSpecificPath)? Assembly.LoadFile(archSpecificPath): null;}return null;}}}至此,我們便實(shí)現(xiàn)了對(duì) CefSharp 的 AnyCPU 支持。
CefSharp 應(yīng)用支持 AnyCPU 的優(yōu)缺點(diǎn)與解決方案
眾所周知,相對(duì)于 32 位應(yīng)用程序,64 位的應(yīng)用擁有更快運(yùn)行的運(yùn)行速度,以及支持更多的內(nèi)存。相對(duì)于分別對(duì) x86 和 x64 分別發(fā)包的方式,AnyCPU 發(fā)包減少了運(yùn)維成本,同時(shí)降低了客戶下載程序包之后不能運(yùn)行的風(fēng)險(xiǎn)。
但是 AnyCPU 的弊端也是很明顯的:64 位的?libcef.dll?文件達(dá)到了 110兆,即便是本文所示的簡(jiǎn)單示例,全部文件的大小也達(dá)到了三百多兆:
要解決這個(gè)問(wèn)題,我們可以在程序運(yùn)行時(shí)動(dòng)態(tài)去下載對(duì)應(yīng)的依賴文件,該下載操作只要確保在調(diào)用 CefSharp 之前即可。
源代碼
本文源代碼:https://gitee.com/coderbusy/demo/tree/master/WinForm/CefSharpDemo
總結(jié)
以上是生活随笔為你收集整理的让 CefSharp.WinForms 应用程序同时支持32位(x86)和64位(x64)的解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Docker Vs Podman
- 下一篇: 如何使用 C# 中的 Action, F