• C# CEFSharp WPF开发桌面程序实现“同一网站多开”


    孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说:“对呀,对呀!CEFSharp,你用过么?访问同一网址实现多开怎么实现?比如我有3个淘宝店,我想同时登录维护,就像传说中的指纹浏览器那样实现cookie和session隔离?”

    前言

    大家好,我是44岁的大龄程序员码农阿峰。好久没有开发过桌面软件了,记得还是在2018年开发过winform,这次用wpf实现了CEFSharp访问同一网址实现多开。官方的示例是访问不同的网站可以互不干扰。其实搜索引擎刚开始就帮我搜到了解决办法,不过是我当时没有意识到那些文字对我有帮助。几番趟坑,才得以解决。

    1)关键实现

    直接上代码:

     

    复制代码
    /// 
            /// 初始化浏览器集合
            /// 
            public void InitDictionary()
            {
                foreach (ChatUser user in LocalAccount)
                {
                    if (!Dict.ContainsKey(user.id))
                    {
                        #region 初始化ChromiumWebBrowser
                        string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Cache\\Cache_" + user.id.ToString());
                        if (!Directory.Exists(path))
                            Directory.CreateDirectory(path);
                        var setting = new RequestContextSettings()
                        {
                            CachePath = path,
                            PersistSessionCookies = true,
                            PersistUserPreferences = true
                        };
                        var context = new RequestContext(setting);
                        var cookieManager = context.GetCookieManager(null);
                        //这样设置的cookie不是全局的,只有当前browser才能访问
                        cookieManager.SetCookie("dxl.cn", new Cookie
                        {
                            Name = $"cookie{user.nickname}",
                            Value = $"cookievalue{user.nickname}",
                            Path = path
                        });
                        ChromiumWebBrowser chromeBrowser = new ChromiumWebBrowser()
                        {
                            Address = config.AppSettings.Settings["ChatUrl"].Value,
                            RequestContext = context,
                            MenuHandler = new NullMenuHandler(),
                            LifeSpanHandler = new LifeSpanHandler(),
                            Visibility = Visibility.Hidden
                        };
                        chromeBrowser.JavascriptObjectRepository.Settings.LegacyBindingEnabled = true;
                        chromeBrowser.JavascriptObjectRepository.Register("bound", obj, false);
                        #endregion
                        obj.WebBrowserCallback += Obj_WebBrowserCallback;
                        user.msgNum = null;
                        chromeBrowser.LoadUrl(config.AppSettings.Settings["ChatUrl"].Value.Replace("login", "sso") + $"?token={user.token}");
                        Dict.Add(user.id, chromeBrowser);
                        mainWindow.MainGrid.Children.Add(chromeBrowser);
                    }
                }
                AccountCountText = $"{LocalAccount.Count}/{config.AppSettings.Settings["MaxAccountCount"].Value}";
                if (AccountPlusVisibility != Visibility.Visible)
                {
                    AccountPlusVisibility = Visibility.Hidden;
                }
            }
    复制代码

    这是ViewModel的代码,下面是页面的

    "1" BorderBrush="Transparent" Background="#f0f0f0" BorderThickness="0" >
                    "MainGrid"/>
                
    MainGrid就是多个ChromeBrowser的父容器,在切换账户的使用显示当前账户对应的ChromeBrowser其他的隐藏。
    复制代码
     public void ChangeBrowser(object xaml_obj)
            {
                var array = xaml_obj as object[];
                if (array != null && array.Length == 2)
                {
                    Grid mainGrid = array[0] as Grid;
                    ChatUser user = array[1] as ChatUser;
                    if (user != null)
                    {
                        CurrentBrowser = Dict[user.id];
                        foreach (var chromeBrowser in mainGrid.Children)
                        {
                            if (chromeBrowser == CurrentBrowser)
                            {
                                ((ChromiumWebBrowser)chromeBrowser).Visibility = Visibility.Visible;
                            }
                            else
                            {
                                ((ChromiumWebBrowser)chromeBrowser).Visibility = Visibility.Hidden;
                            }
                        }
                    }
                }
            }
    复制代码

    以上是按点击切换浏览器的代码。 

     

    复制代码
      /// 
            /// Cef 参数
            /// 
            /// 
            public static CefSettings GetCefSettings()
            {
                var settings = new CefSettings
                {
                    Locale = "zh-CN",
                    AcceptLanguageList = "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
                    RemoteDebuggingPort = 8088,
                    LogSeverity = LogSeverity.Disable,
                    PersistSessionCookies = true,//Persistent Cookies会被保存在一个浏览器的一个子文件夹中
                    UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
                    IgnoreCertificateErrors = true,
                    MultiThreadedMessageLoop = true,//让浏览器的消息循环在一个单独的线程中执行,建议设置成true,具体含义看看浏览器消息处理。
                    WindowlessRenderingEnabled = true,//如果不开启好多用那种JSUI的控件的网站 都有问题
                    CachePath = AppDomain.CurrentDomain.BaseDirectory + "/Cache",//缓存目录
                };
                settings.CefCommandLineArgs.Add("disable-application-cache", "1");//不要缓存
                settings.CefCommandLineArgs.Add("disable-gpu", "1");//去掉gpu,否则chrome显示有问题
                settings.CefCommandLineArgs.Add("enable-media-stream", "1"); //Enable WebRTC
                settings.CefCommandLineArgs.Add("proxy-auto-detect", "0");
                settings.CefCommandLineArgs.Add("no-proxy-server", "1");
                settings.CefCommandLineArgs.Add("allow-running-insecure-content", "1");
                //settings.CefCommandLineArgs.Add("ppapi-flash-version", "34.0.0.118"); //设置flash插件版本
                //string flashFilePath = Application.StartupPath + @"\Plugins\pepflashplayer.dll";
                //settings.CefCommandLineArgs.Add("ppapi-flash-path", flashFilePath);
                //settings.CefCommandLineArgs.Add("enable-system-flash", "1");
                settings.CefCommandLineArgs.Add("enable-npapi", "1");
                settings.CefCommandLineArgs.Add("ppapi-out-of-process", "1");
                settings.CefCommandLineArgs.Add("plugin-policy", "allow");
    
                return settings;
            }
    复制代码

     

    以上是主程序进程启动时的初始化代码。

     

    后记

    WPF是数据驱动这真是比较香,做出来的程序对高DPI设备支持也好,可惜就是最后打包出来300多M老板接受不了,一番优化最后实现100M以下,奈何一搞C++的后生动作比我快,程序打包变态的小,程序性能貌似也比我的强。所以悲剧了,我最终二选一被PK下来,我的程序最终也是没有被使用。把关键代码分享出来,希望可以帮到有需求的人。

     

    复制代码
    var settings = new CefSettings();
    settings.CefCommandLineArgs.Add("disable-extensions", "1");
    settings.CefCommandLineArgs.Add("disable-plugins", "1");
    settings.CefCommandLineArgs.Add("disable-session-storage", "1");
    settings.CefCommandLineArgs.Add("disable-web-security", "1");
    settings.CefCommandLineArgs.Add("disable-pdf-extension", "1");
    settings.CefCommandLineArgs.Add("disable-pdf-viewer", "1");
    settings.CefCommandLineArgs.Add("disable-javascript", "1");
    settings.CefCommandLineArgs.Add("disable-local-storage", "1");
    settings.CefCommandLineArgs.Add("disable-webgl", "1");
    settings.CefCommandLineArgs.Add("disable-geolocation", "1");
    settings.CefCommandLineArgs.Add("disable-default-apps", "1");
    settings.CefCommandLineArgs.Add("disable-remote-fonts", "1");
    settings.CefCommandLineArgs.Add("disable-remote-images", "1");
    settings.CefCommandLineArgs.Add("disable-remote-scripts", "1");
    settings.CefCommandLineArgs.Add("disable-remote-video", "1");
    settings.CefCommandLineArgs.Add("disable-remote-webaudio", "1");

    var browser = new ChromiumWebBrowser("https://www.example.com", settings);
    复制代码

     

    AI说的办法我没有试过,大家说它说得对吗?

  • 相关阅读:
    Primavera P6 Calendars 全局日历和项目日历Calendar
    c++ 模板详解
    【装箱问题】基于Shuffled Complex Evolution (SCE) 算法解决装箱问题 (BPP)附matlab代码
    Tensorflow C++部署实战-linux平台上C++编译环境建立(3)
    CDH安装步骤
    Redis数据类型之Stream系列一
    [题] 快速排序 #分治
    java 两个list的交集
    使用 jdbc 技术升级水果库存系统(后端最终版本,不包含前端)
    一个例子了解交叉编译
  • 原文地址:https://www.cnblogs.com/datacool/p/17599302.html