关于C#使用CEF的详解
欢迎观赏此教程
这是一篇帮助萌新进行快速了解CefSharp的教程。作为一个摸索了五天的咸鱼。遇到了各种解决不了的坑 最后还是解决了、
如何快速集成CefSharp到项目?
在VS中打开 工具 -> NuGet程序包管理器 -> 管理解决方案的NuGet包
然后进行搜索 CefSharp.WinForms 或者 cef
点击安装 然后等待一会儿 会出现一个READ.MD的文本。 表示已经安装引用成功
标记文本
如何使用初始运行简单的项目?
在上一步集成之后 很多童鞋可能会问了 集成之后干什么 怎么才能 运行项目
?
表急 , 很快就能运行看效果
滴
下列是代码片段. 先对浏览器进行 初始化 然后就能进行使用了
bool IsProxy
//初始化浏览器信息
CefSettings settings = new CefSettings()
{
IgnoreCertificateErrors = true,
};
settings.UserAgent = UserAgent;//设置UA的头信息
settings.IgnoreCertificateErrors = true;//忽略错误信息
settings.CachePath = Environment.CurrentDirectory("\Cache");//设置浏览器缓存路径
//是否配置代理
if (IsProxy) {
//对浏览器进行使用代理 可以二选一
settings.CefCommandLineArgs.Add("--proxy-server", $"http://127.0.0.1:1080");
CefSharpSettings.Proxy = new ProxyOptions("127.0.0.1", "1080");
}
//配置语言环境信息【中国】
settings.Locale = "zh-CN";
settings.AcceptLanguageList = "zh-CN";
//配置GPU信息【使用GPU进行加速】
settings.CefCommandLineArgs.Add("disable-gpu", "1");
//禁用falsh【不需要禁用的话可以删除】
settings.CefCommandLineArgs.Add("ppapi-flash-version", "");
settings.CefCommandLineArgs.Add("ppapi-flash-path", "");
settings.CefCommandLineArgs.Add("--disable-bundled-ppapi-flash", "");
//初始化加载配置信息到浏览器
Cef.Initialize(settings);
//开启注册JS对象到浏览器【可选】
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
然后即可进行 调用了
//因为这个浏览器内核不是控件 所以利用代码进行的调用
string _urlPath = "http://www.baidu.com";//设置访问的地址
ChromiumWebBrowser web = new ChromiumWebBrowser(_urlPath);//初始化浏览器对象
this.Controls.Add(web);//添加浏览器到窗体
OK,运行看看 是不是运行起来了 !
进阶版:一.网页右键菜单 : IContextMenuHandler
如果您要自定义网页的右键菜单 那么请写一个类 并继承 IContextMenuHandler
类
//在右键菜单弹出之前
public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model) {
//清除右键菜单信息
model.Clear();
//保存页面地址
lastSelText = parameters.SelectionText;
// 开始复制网址到剪切板
if (parameters.SelectionText.CheckIfValid()) {
model.AddItem(CefMenuCommand.Copy, "Copy");
model.AddSeparator();
}
//移除已经存在的菜单
if (parameters.LinkUrl != "") {
model.AddItem((CefMenuCommand)OpenLinkInNewTab, "在页面中打开");
model.AddItem((CefMenuCommand)CopyLinkAddress, "复制链接地址");
model.AddSeparator();
}
if (parameters.HasImageContents && parameters.SourceUrl.CheckIfValid()) {
//在图片上被点击的时候
}
if (parameters.SelectionText != null) {
//选中页面文本的时候
}
//加载右键菜单项
//#if DEBUG
model.AddItem((CefMenuCommand)ShowDevTools, "开发者工具");
model.AddItem(CefMenuCommand.ViewSource, "查看源码");
model.AddSeparator();
//#endif
model.AddItem((CefMenuCommand)RefreshTab, "刷新页面");
model.AddItem((CefMenuCommand)CloseTab, "关闭页面");
}
//右键菜单被点击之时
public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags) {
int id = (int)commandId;
if (id == ShowDevTools) {
browser.ShowDevTools();
}
if (id == CloseDevTools) {
browser.CloseDevTools();
}
if (id == SaveImageAs) {
browser.GetHost().StartDownload(parameters.SourceUrl);
}
if (id == SaveLinkAs) {
browser.GetHost().StartDownload(parameters.LinkUrl);
}
if (id == OpenLinkInNewTab) {
ChromiumWebBrowser newBrowser = myForm.AddNewBrowserTab(parameters.LinkUrl, false, browser.MainFrame.Url);
}
if (id == CopyLinkAddress) {
Clipboard.SetText(parameters.LinkUrl);
}
if (id == CloseTab) {
myForm.InvokeOnParent(delegate () {
myForm.CloseActiveTab();
});
}
if (id == RefreshTab) {
myForm.InvokeOnParent(delegate () {
myForm.RefreshActiveTab();
});
}
return false;
}
//关闭右键菜单的时候
public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame) {
}
//运行右键菜单
public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback) {
//是否要显示默认的菜单
return false;
}
进阶版:二.网页操作回调 : ILifeSpanHandler
同理 继承 ILifeSpanHandler
//浏览器在接受到请求之后进行管理时候的处理
public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser) {
}
//在关闭之前
public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser) {
}
//在窗体创建之前的操作
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) {
// 在初始化网页之前新建一个新的标签
newBrowser = null;
myForm.AddNewBrowserTab(targetUrl);
return true;
}
进阶版:三.操作Cookies : ICookieManager
同理。继承:ICookieManager
public bool IsDisposed
{
get
{
throw new NotImplementedException();
}
}
//删除Cookies
public bool DeleteCookies(string url = null, string name = null, IDeleteCookiesCallback callback = null)
{
return true;
}
//释放掉
public void Dispose()
{
throw new NotImplementedException();
}
//清理缓存
public bool FlushStore(ICompletionCallback callback)
{
//测试无效 清理不掉
return true;
}
//设置Cookies
public bool SetCookie(string url, Cookie cookie, ISetCookieCallback callback = null)
{
//记住 Cef.GetGlobalCookieManager() 只能在这里面用 否则会出现内存不能访问的问题!
Cef.GetGlobalCookieManager().SetCookie(url, cookie);
return true;
}
//设置缓存路径
public bool SetStoragePath(string path, bool persistSessionCookies, ICompletionCallback callback = null)
{
return true;
}
//设置支持的方案信息
public void SetSupportedSchemes(string[] schemes, ICompletionCallback callback = null)
{
}
//是否能访问所有的Cookies信息
public bool VisitAllCookies(ICookieVisitor visitor)
{
return true;
}
//是否可访问指定网址的Cookies信息
public bool VisitUrlCookies(string url, bool includeHttpOnly, ICookieVisitor visitor)
{
return true;
}
如果是需要寻找怎么读取Cookies
的话可以直接百度
(*)因为写入Cookies不在这里写的话 就会造成内存不能访问 而导致崩盘!
进阶版:四.Request的回调 : IRequestHandler
同理。继承:IRequestHandler
里面的方法:
//设置是否能读取Cookies信息
public bool CanGetCookies(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request) {
return true;
}
//设置是否能写入Cookies信息
public bool CanSetCookie(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, Cookie cookie) {
return true;
}
//当客户端需要验证的时候 是否调用验证模块
public bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) {
return true;
}
//请求接收资源的时候 是否进行过滤接收自定义数据
public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) {
return null;
}
//在页面加载之前
public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect) {
return false;
}
//请求加载资源之前
public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) {
// 如果指定了网址信息
var tab = myForm.GetTabByBrowser(browserControl);
if (tab != null && tab.RefererURL != null) {
// 设置直接跳转
request.SetReferrer(tab.RefererURL, ReferrerPolicy.Always);
}
//如果是禁用不加载图片的话
if (myForm.LoadImage == false)
{
//如果类型是图片 就退出【表示不加载图片信息】
if (request.ResourceType == ResourceType.Image)
{
return CefSharp.CefReturnValue.Cancel;
}
}
return CefSharp.CefReturnValue.Continue;
}
//设置是否能进行SSL验证
public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) {
return true;
}
//打开网页之后需要变动 可在这配置 【会在页面呈现在UI之前进行操作】
public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) {
return false;
}
//插件崩溃的时候触发
public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath) {
}
//在URL是个未知协议的时候进行触发
public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url) {
return true;
}
//在JAVAScript进行加载完毕的时候
public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) {
callback.Continue(true);
return true;
}
//在渲染过程中意外终止
public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status) {
}
//当渲染视图与浏览器关联时,在CEF UI线程上调用 准备好在呈现过程中接收/处理IPC消息。
public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser) {
}
//资源加载完成后,在CEF IO线程上调用。
public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) {
}
//重定向资源加载时在IO线程上调用。 CefSharp.IRequest.Url
public void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) {
}
//收到资源响应时,在CEF IO线程上调用。允许 正常加载的资源返回false。重定向或重试资源
//修改请求(url,headers或post body)并返回true。响应 无法在此回调中修改对象。
public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) {
int code = response.StatusCode;
// 如果出现404的话
if (code == 404) {
//如果不是本地的链接
if (!request.Url.IsURLLocalhost()) {
// 寻找帮助文档
request.Url = "http://web.archive.org/web/*/" + request.Url;
} else {
// 如果是本地地址 那么进行查找文件IO
request.Url = MainForm.FileNotFoundURL + "?path=" + request.Url.EncodeURL();
}
return true;
}
// 如果找不到文件的话
if (code == 0 && request.Url.IsURLOfflineFile()) {
string path = request.Url.FileURLToPath();
if (path.FileNotExists()) {
// 如果是本地地址 那么进行查找文件IO
request.Url = MainForm.FileNotFoundURL + "?path=" + path.EncodeURL();
return true;
}
} else {
// 如果没有连接的话
if (code == 0 || code == 444 || (code >= 500 && code <= 599)) {
// 显示不能连接的模块
request.Url = MainForm.CannotConnectURL;
return true;
}
}
return false;
}
//选择客户端证书的时候
public bool OnSelectClientCertificate(IWebBrowser chromiumWebBrowser, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback) {
return false;
}
结尾
由此可见,CEF还是很具有强大的扩展功能 不过他是C的底层 所以很多东西都是受保护的 需要继承他的类 进行重载。 这样调用的话 就不会出现内存异常 或者 内存受保护相关的错误了。
最后请大家玩的愉快~