1.从Nuget下载CEF框架
我的示例程序是WPF程序,所以下载的框架是CefSharp.Wpf,你也可以下载Cef的其他版本如CefSharp.WinForms
2.创建一个Wpf窗口:
<Window x:Class="ChromeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cefSharpWPF="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
mc:Ignorable="d"
Title="ChromeWindow" Height="450" Width="800" Closing="Window_Closing">
<DockPanel Name="dockpanel" LastChildFill="True">
<cefSharpWPF:ChromiumWebBrowser Name="mybrower" Address="https://www.cnblogs.com/tuyile006"></cefSharpWPF:ChromiumWebBrowser>
</DockPanel>
</Window>
打开看看效果。这是超简单的使用方式,我就不展示了。
3.让cef chromium支持flash视频播放。
很多网页中有flash,内嵌的chromium浏览器是不支持flash的,必须设置一下。
需要下载一个插件,放到项目中,并随项目发布到输出目录。

主要看构造函数中的代码:
using CefSharp;
using CefSharp.Wpf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows;
namespace xiaoy.Control
{
/// <summary>
/// 谷歌浏览器帮助类(静态类)
/// </summary>
public class ChromeCefHelper
{
private static List<ChromeWindow> webList= new List<ChromeWindow>();
private static object lockObj = new object();
public static string ErrhtmlTemplate = string.Empty;
static ChromeCefHelper()
{
//初始化浏览器设置
if (!Cef.IsInitialized)
{
//打开静态地址
string strMenu = AppDomain.CurrentDomain.BaseDirectory;
//pepflashplayerDLL 地址
string flashPath = strMenu + @"\flashPlugin\pepflashplayer64_32_0_0_414.dll";
CefSettings set = new CefSettings();
set.CachePath = strMenu + "\\cache";
set.PersistSessionCookies = true;
set.LogSeverity = LogSeverity.Disable;
//安全证书
set.CefCommandLineArgs.Add("--ignore-urlfetcher-cert-requests", "1");
set.CefCommandLineArgs.Add("--ignore-certificate-errors", "1");
//开启ppapi-flash
set.CefCommandLineArgs["enable-system-flash"] = "1";
set.CefCommandLineArgs.Add("ppapi-flash-version", "32.0.0.414");
//插入地址
set.CefCommandLineArgs.Add("ppapi-flash-path", flashPath);
//访问本地资源
set.RegisterScheme(new CefCustomScheme
{
SchemeName = CefSharpSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new CefSharpSchemeHandlerFactory()
});
//启用配置
//bool bint= CefSharp.Cef.Initialize(set);
Cef.Initialize(set, performDependencyCheck: false, browserProcessHandler: null);
//错误网页模板
string htmlpath = AppDomain.CurrentDomain.BaseDirectory + "html\\error.html";
ErrhtmlTemplate = File.ReadAllText(htmlpath);
}
}
/// <summary>
/// 自动设置token到cookie中
/// </summary>
public static void SetCookies()
{
if (!string.IsNullOrEmpty(CommCach.Token))
{
lock(lockObj)
{
try
{
//获取portalurl中的域名地址
int starti = CommCach.PortalUrl.IndexOf("//") + 2;
int endi = CommCach.PortalUrl.IndexOf("/", starti);
string domain = CommCach.PortalUrl.Substring(starti, endi - starti);
var cookieManager = CefSharp.Cef.GetGlobalCookieManager();
cookieManager.SetCookieAsync("http://" + domain, new CefSharp.Cookie()
{
Domain = domain,
Name = "Admin-Token",
Value = HttpUtility.UrlEncode(CommCach.Token),
Expires = DateTime.MinValue
});
}
catch(Exception ex)
{
LogHelper.Error("写Cookie失败",ex);
}
}
}
}
/// <summary>
/// 第一次启动
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static ChromeWindow Open(string title,string url)
{
SetCookies();
ChromeWindow cw = new ChromeWindow();
cw.Title = title;
cw.Open(url);
cw.Show();
//cw.WindowStyle = WindowStyle.None;
webList.Add(cw); //放在缓存中 以便退出关闭浏览器
return cw;
}
/// <summary>
/// 在原chrome中改url
/// </summary>
/// <param name="webDriver"></param>
/// <param name="url"></param>
public static void Open(ChromeWindow webDriver, string title, string url)
{
if (webDriver != null)
{
SetCookies();
webDriver.Title = title;
webDriver.Open(url);
}
}
/// <summary>
/// 关闭所有窗口
/// </summary>
public static void CloseAll()
{
foreach (ChromeWindow w in webList)
{
if (w != null)
w.Close();
}
webList.Clear();
}
}
}
ChromeWindow.xaml是要弹的浏览器窗体。在ChromiumWebBrowser对象初始化完之后需要支持直接打开flash播放,不能让用户点播放按钮才播放,这是用户使用习惯。实现如下:
前端窗体可以只放个DockPanel控件,后台代码动态添加浏览器控件
<Window x:Class="xiaoy.ChromeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="ChromeWindow" Height="450" Width="800" Closing="Window_Closing">
<DockPanel Name="dockpanel" LastChildFill="True">
<!--<cefSharpWPF:ChromiumWebBrowser Name="mybrower" Address="https://www.cnblogs.com/tuyile006"></cefSharpWPF:ChromiumWebBrowser>-->
</DockPanel>
</Window>
然后在Browser_IsBrowserInitializedChanged中自动播放flash
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using CefSharp;
using CefSharp.Wpf;
namespace xiaoy.Control
{
/// <summary>
/// ChromeWindow.xaml 的交互逻辑
/// </summary>
public partial class ChromeWindow : Window
{
ChromiumWebBrowser browser = null;
bool bInited = false;//是否初始化完成
public ChromeWindow()
{
InitializeComponent();
//初始化浏览器
InitBrowser();
//Open(url);
}
/// <summary>
/// 初始化浏览器,让其支持flash
/// </summary>
/// <param name="url"></param>
public void InitBrowser()
{
browser = new ChromiumWebBrowser();
// browser.RequestHandler=new CustomRequestHandler();
browser.KeyboardHandler = new CustomKeyBoardHander();
BrowserSettings bset = new BrowserSettings();
bset.Plugins = CefState.Enabled;
bset.ApplicationCache = CefState.Enabled;
//关于跨域限制
//bset.WebSecurity = CefState.Disabled;
browser.BrowserSettings = bset;
browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged;
//打开网页
//browser.Load(strMenu + htmlDidr);
//绑定JS
//browser.RegisterJsObject("callbackObj", new CallbackObjectForJs());
// browser.FrameLoadEnd += Browser_FrameLoadEnd;
this.dockpanel.Children.Add(browser);
}
private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
var visitor = new CookieVisitor(all_cookies => {
var sb = new StringBuilder();
foreach (var nameValue in all_cookies)
sb.AppendLine(nameValue.Item1 + " = " + nameValue.Item2);
//MessageBox.Show("读取到Cookie值:" + sb.ToString());
//LogHelper.Info("读取到Cookie值:" + sb.ToString());
});
Cef.GetGlobalCookieManager().VisitAllCookies(visitor);
}
private void Browser_IsBrowserInitializedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
try
{
if ((bool)e.NewValue == true)
{
bInited = true;
}
if (browser.IsBrowserInitialized)
{
//自动播放flash
Cef.UIThreadTaskFactory.StartNew(() =>
{
string error = "";
var requestContext = browser.GetBrowser().GetHost().RequestContext;
requestContext.SetPreference("profile.default_content_setting_values.plugins", 1, out error);
});
}
}
catch(Exception ex)
{
LogHelper.Error(ex);
}
}
/// <summary>
/// 打开指定网址
/// </summary>
/// <param name="url">网址</param>
public void Open(string url)
{
//打开网页
if (browser != null && browser.IsBrowserInitialized)
browser.Load(url);
else
browser.Address = url;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (browser != null)
{
browser.Dispose();
browser = null;
}
}
}
}
4.用cef给Chromium浏览器写Cookie
有时候需要实现免登录打开网页,即你之前已经登录过网站,打开该网站内其他网页不需要再登录。这就需要根据该网页的验证方式进行相应适配了,比如写cookie,以下就是写cookie的实现:
/// <summary>
/// 自动设置token到cookie中
/// </summary>
public static void SetCookies()
{
if (!string.IsNullOrEmpty(CommCach.Token))
{
lock(lockObj)
{
try
{
//获取portalurl中的域名地址
int starti = CommCach.PortalUrl.IndexOf("//") + 2;
int endi = CommCach.PortalUrl.IndexOf("/", starti);
string domain = CommCach.PortalUrl.Substring(starti, endi - starti);
var cookieManager = CefSharp.Cef.GetGlobalCookieManager();
cookieManager.SetCookieAsync("http://" + domain, new CefSharp.Cookie()
{
Domain = domain,
Name = "Admin-Token",
Value = HttpUtility.UrlEncode(CommCach.Token),
Expires = DateTime.MinValue
});
}
catch(Exception ex)
{
LogHelper.Error("写Cookie失败",ex);
}
}
}
}
以上是我测试的代码,请根据你自己的实际要求,修改Cookie名称和域名等。 注意SetCookieAsync的url要是http://开头。domain不要http
5.用Cef在http请求头中加字段
这个也是一个常见需求。以下代码实现在http头中增加access-token字段。
增加一个ResourceRequestHandler的自定义类:
using CefSharp;
using CefSharp.Handler;
namespace xiaoy.Control
{
public class CustomResourceRequestHandler : ResourceRequestHandler
{
protected override CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame,
IRequest request, IRequestCallback callback)
{
var headers = request.Headers;
//自动增加access-token
if (!string.IsNullOrEmpty(CommCach.Token))
{
bool bExist = false;
foreach (string k in headers.Keys)
{
if (string.Compare(k, "access-token", true) == 0)
{
bExist = true;
break;
}
}
if (bExist)
headers["access-token"] = CommCach.Token;
else
headers.Add("access-token", CommCach.Token);
}
request.Headers = headers;
return CefReturnValue.Continue;
}
}
public class CustomRequestHandler : RequestHandler
{
protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser,
IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
{
return new CustomResourceRequestHandler();
}
}
}
然后在浏览器对象创建后,增加handler
browser = new ChromiumWebBrowser(); browser.RequestHandler=new CustomRequestHandler();
6.用Cef打开网页访问本地图片等资源
如果要打开本地网页,cef支持loadhtml方法,但是浏览器权限无法打开本地资源,必须做特殊处理才可以。
官网的方案如下:https://github.com/cefsharp/CefSharp/wiki/General-Usage#initialize-and-shutdown
using CefSharp;
using System;
using System.IO;
using System.Reflection;
namespace xiaoy.Control
{
public class CefSharpSchemeHandlerFactory : ISchemeHandlerFactory
{
public const string SchemeName = "custom";
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
var fileName = request.Url.Replace(SchemeName+"://", "");
Assembly ass = Assembly.GetExecutingAssembly();
String resourcePath = ass.GetName().Name + "." + fileName.Replace("/", ".");
Stream resource= ass.GetManifestResourceStream(resourcePath);
if (resource!=null)
{
var fileExtension = Path.GetExtension(fileName);
return ResourceHandler.FromStream(resource, mimeType:Cef.GetMimeType(fileExtension));
}
return null;
}
}
}
然后在初始化cef的时候(上文ChromeCefHelper中)添加
//访问本地资源
set.RegisterScheme(new CefCustomScheme
{
SchemeName = CefSharpSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new CefSharpSchemeHandlerFactory()
});
//启用配置
//bool bint= CefSharp.Cef.Initialize(set);
Cef.Initialize(set, performDependencyCheck: false, browserProcessHandler: null);
因为你定义的schemename是“custom”,所以在你本地要打开的html中,资源地址要用“custom://”开头。
<div class="content-container">
<div class="head-line">
<img src="custom://html/error.png" alt="" width="120"/>
</div>
<div class="subheader">
{errorTitle}</div>
<div class="hr"></div>
<div class="context">
<p>
{errorContent}
</p>
</div>
</div>
然后可以直接调用 browser.LoadHtml方法显示本地网页了。本地网页模板建议先读取到内存中。
/// <summary>
/// 显示错误信息
/// </summary>
/// <param name="errTitle"></param>
/// <param name="errContent"></param>
public void ShowError(string errTitle,string errContent)
{
Task.Factory.StartNew(() => {
//网页中可替换的变量: {imagePath} {errorTitle} {errorContent}
//string imgpath = AppDomain.CurrentDomain.BaseDirectory + "html\\error.png";
//imgpath= imgpath.Replace("\\", "/");
string imgpath = CefSharpSchemeHandlerFactory.SchemeName+"://html/error.png";
//
string html = ChromeCefHelper.ErrhtmlTemplate.Replace("{imagePath}", imgpath).Replace("{errorTitle}", errTitle).Replace("{errorContent}", errContent);
//string html = string.Format(ChromeCefHelper.ErrhtmlTemplate, errTitle, errContent);
while (bInited == false)
Thread.Sleep(50);
browser.LoadHtml(html, CefSharpSchemeHandlerFactory.SchemeName+"://error.html");
});
}
7.Cef中让浏览器支持F5/F12等快捷键
内嵌的chromium浏览器是默认不支持快捷键的,需要添加keyboardhandler支持。
using CefSharp;
using System;
using System.Windows.Forms;
namespace xiaoy.Control
{
public class CustomKeyBoardHander : IKeyboardHandler
{
public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
if (type == KeyType.KeyUp && Enum.IsDefined(typeof(System.Windows.Forms.Keys), windowsKeyCode))
{
var key = (Keys)windowsKeyCode;
switch (key)
{
case Keys.F12:
browser.ShowDevTools();
break;
case Keys.F5:
if (modifiers == CefEventFlags.ControlDown)
{
//MessageBox.Show("ctrl+f5");
browser.Reload(true); //强制忽略缓存
}
else
{
//MessageBox.Show("f5");
browser.Reload();
}
break;
}
}
return false;
}
public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode,
int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
{
return false;
}
}
}
然后在浏览器对象创建后增加handler
browser = new ChromiumWebBrowser(); // browser.RequestHandler=new CustomRequestHandler(); browser.KeyboardHandler = new CustomKeyBoardHander();
转自:https://www.cnblogs.com/tuyile006/p/13852630.html
