前几天在研究怎么定制 CefSharp 控件. CefSharp 控件是一个封装了 CEF(Chromium Embedded Framework) 的 .NET 类库, 它可以实现一个简单浏览器的功能, 可以在 WPF/WinForms 中使用.
其实 CefSharp 控件在 C# 层面已经把接口封装的不错了, 很多功能可以直接使用. 但是如果要扩展某些接口, 则必须修改 CEF 或者 Chromium 里面的代码, 再重新编译出 CEF 发行包, 从 CEF 发行包制作成 NuGet 使用的 nupkg 文件.
开源项目的英文文档有些地方没有讲到, 幸亏我是搞 Chromium 开发, 不然真是坑死了. 写篇文章总结一下.
编译 CEF 工程
因为开发 CefSharp 过程需要修改 CEF 内核的代码实现一些功能, 而 CEF 代码又是基于 Chromium 的, 所这里想讲一讲如何搭建 CEF 和 Chromium 的开发环境.
环境要求
电脑网络需要能够翻墙, 因为代码和相关的工具需要翻墙才能更新.
系统至少是 win7 x64 或者更新的版本, 因为 Chromium 不支持 32 位操作系统编译代码. 因为需要 Win 8.1 SDK, 所以使用 win 8.1 系统比较合适.
电脑需要安装 Visual Studio 2013 Update 4, 目前 Chromium 只支持这个版本的 VS 编译代码.
电脑至少 8GB 内存, 否则可能链接不成功.
为了加快编译速度, 建议使用 SSD 固态硬盘.
目前我电脑的硬件是 i7 4790K CPU,32GB DDR3 内存, 固态硬盘, 这样的配置编译一次 CEF 代码的 Release 版需要 75 分钟.
设置系统区域
默认的中文操作系统系统区域设置的值为 "中文 (简体, 中国)", 但是这样的区域设置编译 CEF 代码无法通过, 需要把系统区域设置成 "英语 (美国)". 打开 "控制面板", 点开 "区域"->"管理", 点击 "更改系统区域设置", 把 "区域设置" 更改成 "英语 (美国)". 更改完成之后需要重启一次电脑. 重启完电脑再确认一下是否更改成功.
安装配置 Depot Tools 工具
CEF 和 Chromium 工程是靠 Depot Tools 工具来管理源代码的, 所以需要先安装 Depot Tools 工具.
Chromim 安装 Depot Tools 工具的教程如下: http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up .
从上面这个教程里总结到以下简单步骤:
从这里下载 Depot Tools 安装包 https://src.chromium.org/svn/trunk/tools/depot_tools.zip .
把下载好的安装包解压到一个英文路径的目录, 比如 E:depot_tools.
将 E:depot_tools 路径加入到系统的环境变量 Path 中.
配置 Depot Tools 中的 git 工具. 打开 cmd, 按照以下规则运行以下命令:
- C++
- $ git config --global user.name "John Doe"
- $ git config --global user.email "jdoe@email.com"
$ git config --global core.autocrlf false
$ git config --global core.filemode false
$ git config --global color.ui true
$ git config --global user.name "John Doe"$ git config --global user.email "jdoe@email.com"$ git config --global core.autocrlf false$ git config --global core.filemode false$ git config --global color.ui true
获取 CEF 代码
CEF 工程已经为我们提供了一个 automate-git.py 脚本来更新代码, 下载地址是: https://bitbucket.org/chromiumembedded/cef/raw/master/tools/automate/automate-git.py .
在 E 盘建立一个 cef 目录, 把下载的 automate-git.py 文件放在这个目录. 并在这个 cef 目录下建立一个名为 3.2454.1344_update.bat 的文件, 其文件中内容如下:
- C++
- set GYP_GENERATORS=ninja,msvs-ninja
- set GYP_MSVS_VERSION=2013
- set GYP_DEFINES=disable_nacl=1
- set DEPOT_TOOLS_WIN_TOOLCHAIN=0
- python automate-git.py --download-dir="E:/cef/download" --branch=2454 --no-build --depot-tools-dir="E:/depot_tools"
- pause
set GYP_GENERATORS=ninja,msvs-ninjaset GYP_MSVS_VERSION=2013set GYP_DEFINES=disable_nacl=1set DEPOT_TOOLS_WIN_TOOLCHAIN=0python automate-git.py --download-dir="E:/cef/download" --branch=2454 --no-build --depot-tools-dir="E:/depot_tools"pause
在 cmd 中运行 3.2454.1344_update.bat 批处理文件就会自动获取代码以及对应的开发工具. 获取到的代码会放到 E:cefdownload 目录.
注意: CefSharp 未来不再支持 xp 系统了, 目前支持 xp 系统的最新 CefSharp 版本是 3.2454.1344, 基于的 Chromium 版本是 45, 所以我们编译的对应 CEF 代码分支是 2454. 参见这个文档 https://github.com/cefsharp/CefSharp/wiki/Windows-XP-No-Longer-Supported .
运行 3.2454.1344_update.bat 更新的代码大小 10GB 左右, 还需要网络能够翻墙, 所以持续的时间很长, 如果中间有失败, 可能需要重新开始.
编译 CEF 代码
更新好 CEF 代码后, 就可以编译了. 在 E:cef 目录建立一个名为 3.2454.1344_all.bat 的文件, 其内容如下:
- C++
- set GYP_GENERATORS=ninja,msvs-ninja
- set GYP_MSVS_VERSION=2013
- set GYP_DEFINES=disable_nacl=1
- set DEPOT_TOOLS_WIN_TOOLCHAIN=0
- python automate-git.py --download-dir="E:/cef/download" --branch=2454 --force-distrib --force-build --depot-tools-dir="E:/depot_tools"
- pause
set GYP_GENERATORS=ninja,msvs-ninjaset GYP_MSVS_VERSION=2013set GYP_DEFINES=disable_nacl=1set DEPOT_TOOLS_WIN_TOOLCHAIN=0python automate-git.py --download-dir="E:/cef/download" --branch=2454 --force-distrib --force-build --depot-tools-dir="E:/depot_tools"pause
在 cmd 中运行 3.2454.1344_all.bat, 就开始编译 CEF, 这个过程需要编译 debug 和 release 版本, 每次需要编译大概 14000 个文件, 总共编译时间为 3 小时左右.
最终编译出的 E:cefdownloadchromiumsrccefbinary_distribcef_binary_3.2454.1344.g2782fb8_windows32.zip 就是我们所需要的.
生成 nupkg 包
一般情况下使用 CefSharp 控件, 是用 nuget 程序包管理工具来获取对应的 nupkg 包, 然后自动添加到 c# 工程中. 因为我们自己定制 CefSharp, 则是自己生成 nupkg, 然后手动添加到 c# 工程中.
CefSharp 的 WPF 程序最终发布使用, 依赖以下 5 个 nupkg 包:
cef.redist.x86.3.2454.1344.nupkg,32 位程序 CEF nupkg 包.
cef.redist.x64.3.2454.1344.nupkg,64 位程序 CEF nupkg 包. 这个 64 位包是可选的, 目前我们构造的都是 32 程序, 不使用这个包. 但是因为内部依赖关系, 还是带上这个包.
cef.sdk.3.2454.1344.nupkg,CefSharp 中间工程依赖这个包.
CefSharp.Common.45.0.0.nupkg,CefSharp 控件基础 nupgk 包.
CefSharp.Wpf.45.0.0.nupkg,CefSharp 控件 WPF nupgk 包. 构建 WPF 程序需要依赖这个包.
生成 CEF nupkg 包
我们先来生成 CEF nupkg 包, 这个需要根据 cef-binary 项目 https://github.com/cefsharp/cef-binary 来操作.
我们先获取到 cef-binary 项目代码到 E:githubcef-binary 目录. 然后把编译生成的 CEF binary_distribcef_binary_3.2454.1344.g2782fb8_windows32.zip 解压到 E:githubcef-binarycef_binary_3.y.z_windows32 目录. 因为实际上我只需要 32 位 nupkg 包, 所以我们没有在 CEF 工程中编译 64 位 CEF 模块, 我们直接去 CEF builds 网站下载 64 位的发行包. 同理, 把这个下载的发行包文件解压放到 cef_binary_3.y.z_windows64 目录.
然后用 PowerShell 来运行 E:githubcef-binarybuild.ps1 文件. 这一步可能会失败, 提示 NuGet.exe 错误. 原因是 %AppData%LocalNuGetNuGet.exe 是错误的, 这个需要拷贝一个正常 NuGet.exe 文件到那个目录.
运行完 E:githubcef-binarybuild.ps1, 会在 E:githubcef-binaryNuGet 目录生成以下几个文件:
- cef.redist.x64.3.2454.1344.nupkg
- cef.redist.x86.3.2454.1344.nupkg
- cef.sdk.3.2454.1344.nupkg
生成 CefSharp nupkg 包
我们先获取 CefSahrp 项目的代码 https://github.com/cefsharp/CefSharp . 然后配置 NuGet.config 的依赖 nupkg 包到 cef-binary 工程生成的 nupkg 包目录. 然后用 vs 打开 E:githubCefSharpCefSharp3.sln, 开始编译工程. 这一步会自动使用我们生成的 nupkg 包.
编译 CefSharp3.sln 成功之后, 在用 PowerShell 打开 E:githubCefSharpbuild.ps1 文件, 这一步会生成以下 nupkg 文件:
- CefSharp.Common.45.0.0.nupkg
- CefSharp.OffScreen.45.0.0.nupkg
- CefSharp.WinForms.45.0.0.nupkg
- CefSharp.Wpf.45.0.0.nupkg
其中, CefSharp.Common.45.0.0.nupkg 和 CefSharp.Wpf.45.0.0.nupkg 是我们所需要的.
使用 nupkg 包
配置本地程序包源
把 cef-binary 和 CefSharp 工程生成的 nupkg 文件放到一个目录, 比如 E:oschinaCefSharpLocal-package-source 目录. 建立一个 Wpf 工程 WpfApplicationDemo. 然后从 "工具"->"NuGet 程序包管理器"->"程序包管理器设置" 打开设置, 选择 "程序包源", 如图:
我们设置添加一个本地的 nupgk 源, 叫做 "Local-package-source", 它的源地址是 E:oschinaCefSharpWpfApplicationDemo..Local-package-source, 源地址目录存放的是我们之前生成的那些 nupgk 文件. 并且把我们的源放到第一位, 在系统默认的 nuget.org 前面. 这么做的理由是系统默认的 nuget.org 源里面也有 CefSharp 等控件, 会覆盖掉我们本地的 CefSharp 控件, 从而导致功能不生效.
使用 CefSharp.Wpf 控件
这里有篇文档介绍如何使用 CefSharp.Wpf 控件, http://www.codeproject.com/Articles/881315/Display-HTML-in-WPF-and-CefSharp-Tutorial-Part .
我以 WpfApplicationDemo 为例子简单介绍一下.
首先设置工程的配置管理器. 从 Any CPU 的配置拷贝过来, 新建一个 x86 的配置, 然后项目的工程选择成 x86. 然后编辑代码, 打开 MainWindow.xaml 文件, 编辑以下代码:
- C++
- <Window x:Class="WpfApplicationDemo.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <cefSharp:ChromiumwebBrowser Grid.Row="0"
- Address="https://www.baidu.com/" />
- </Grid>
- </Window>
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" Title="MainWindow" Height="350" Width="525"> Address="https://www.baidu.com/" />
红色部分代码是我们新加的. 我们代码中添加了 cefSharp 控件, 并且打开了 https://www.baidu.com/ .
编译工程, 就会根据依赖自动安装 CefSharp.Wpf 控件. 我们打开 NuGet 程序包管理器, 选择已安装的包, 如图:
选择 CefSharp.Wfp 包, 可以看到创建者是 http://blog.gclxry.com/ , 则表明我们正确的使用了我们自己生成的包.
运行工程, 可以看到界面如下图所示:
来源: http://blog.gclxry.com/build-cefsharp/