背景: 一个老的客户端项目,没人维护了,改为 H5 方案实现

部分专用硬件驱动限制, windows 系统锁定在 windows7, .net 版本锁定在 .net4, 原客户端采用的 wpf 方案,搜索后发现cef 版本最高 Install-Package CefSharp.Wpf -Version 49.0.1 49 版本(2016/6/1)。

有几个问题要解决

1. 去掉跨域限制

// 1.全局设置,对整个进程生效
CefSettings setting = new CefSharp.CefSettings();
setting.CefCommandLineArgs.Add("disable-web-security", "1");
Cef.Initialize(setting);
// 2. 也可以针对单个域设置
//Cef.AddCrossOriginWhitelistEntry();

2. 设置 proxy

// 方法1. 全局设置,设置后不可更改,需要更改只能重启程序
CefSettings setting = new CefSharp.CefSettings();
setting.CefCommandLineArgs.Add("proxy-server", "http://test.com:9999");
setting.CefCommandLineArgs.Add("proxy-bypass-list", "127.*,localhost");
Cef.Initialize(setting);

// 方法2. 但是程序需要修改proxy,希望修改后立即成效;修改后重启程序体验有点差
ChromiumWebBrowser wb = new ChromiumWebBrowser();
wb.RequestContext = new RequestContext();
wb.IsBrowserInitializedChanged += (s,e) =>{
    //var wb = sender as ChromiumWebBrowser;
    if (!wb.IsBrowserInitialized)
        return;

    // NOTE: 重点在这一行。 
    Cef.UIThreadTaskFactory.StartNew(() =>
    {
        var context = wb.RequestContext;
        // debug, 查看当前配置
        //var settings = context.GetAllPreferences(true);
        // 查看是否可以设置 proxy
        var canSetProxy = context.CanSetPreference("proxy");
        // 方式 1 设置全局 proxy 后,这里不能再设置;设置不会生效
        if(canSetProxy){
            var v = new Dictionary<string, object>
            {
                ["mode"] = "fixed_servers",
                ["server"] = "http://test.com:9999",
                ["bypass_list"] = "127.*;localhost", // 127.*,localhost #测试逗号分割也是可以的
            };
            string err;
            var result = context.SetPreference("proxy", v, out err);
        }
    });
};

麻烦就在这一行. Cef.UIThreadTaskFactory.StartNew

按官网的说法:

  1. winform https://cefsharp.github.io/api/63.0.0/html/E_CefSharp_WinForms_ChromiumWebBrowser_IsBrowserInitializedChanged.htm
Occurs when [is browser initialized changed]. 

It's important to note this event is fired on a CEF UI thread, which by default is not the same as your application UI thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang.. To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.

Namespace: CefSharp.WinForms
Assembly: CefSharp.WinForms (in CefSharp.WinForms.dll) Version: 63.0.0.0 (63.0.0.0)
  1. wpf https://cefsharp.github.io/api/63.0.0/html/E_CefSharp_Wpf_ChromiumWebBrowser_IsBrowserInitializedChanged.htm

Event handler that will get called when the browser has finished initializing

按这个文档的说法, 很容易认为注册这个事件, 直接写就好了, 实际是不行,你需要 Cef.UIThreadTaskFactory.StartNew 委托 brower UI thread 执行才可以。

对比排错

  1. .net4 wpf 项目, Install-Package CefSharp.Wpf -Version 49.0.1, var canSetProxy = context.CanSetPreference("proxy"); 返回 false, 不报错,设置后不生效。

  2. .net4.5 wpf 项目, Install-Package CefSharp.Wpf -Version 103.0.80测试, var canSetProxy = context.CanSetPreference("proxy"); 直接异常。

直到这时,才发现是执行线程不对😅

3. 禁用GPU加速

cef默认开启GPU加速, 但是在内嵌环境,chrome的GPU加速进程会频繁交互异常, 导致页面闪跳。

如何确认是GPU硬件加速导致的显示问题?

  1. 查看程序根目录的 debug.log 文件,里边会频繁记录GPU进程崩溃
  2. 查看任务管理器, 正常只有一个 CefSharp.BrowserSubprocess.exe进程,开启GPU就会有两个,另一个是GPU加速进程(chrome是多进程应用,进程之间通过pipe通信)
  3. chrome菜单 -> 更多工具 -> 任务管理器, 打开后可以看到GPU进程信息

chrome GPU 加速官网介绍

解决办法?

cefSetting.CefCommandLineArgs.Add("disable-gpu", "1");, cef 禁用GPU

参考

  1. 高版本设置 proxy,有方便的 helper 方法. https://github.com/cefsharp/CefSharp/wiki/General-Usage#proxy-resolution

  2. cefsharp 添加这个功能的开发日志: https://github.com/cefsharp/CefSharp/issues/3235

  3. Setting proxy bypass list in preferences

    https://magpcss.org/ceforum/viewtopic.php?f=6&t=14097 https://source.chromium.org/chromium/chromium/src/+/main:net/proxy_resolution/proxy_config.cc;l=279?q=proxy_config.cc&ss=chromium

  4. https://github.com/cefsharp/CefSharp/blob/cefsharp/57/CefSharp.Core/RequestContext.h#L305

    Set the value associated with preference name. If value is null the preference will be restored to its default value. SetPreference()

  5. chrome.proxy https://developer.chrome.com/docs/extensions/reference/proxy/

  6. CefSharp 开发触屏终端遇到的问题记录 https://blog.51cto.com/u_15127592/2803343