使用C# CEFSharp在WPF中开发桌面程序实现同一网站多开功能

在网络商业运营领域,同时运营多个淘宝店铺的现象屡见不鲜。为了满足这一需求,实现同一网址的多开功能变得尤为关键。这一需求虽然实用,但实现起来却面临诸多挑战。在这个过程中,技术人员们也经历了不少喜怒哀乐。

开发经历回顾

阿峰,今年44岁,是个久未涉足桌面软件开发的程序员。自2018年那次经历后,他最近又接手了一个WPF项目,任务是实现网址的多开功能。回想起那时候,从接到任务的那一刻起,他就感受到了满满的未知和挑战。一开始,看到官方提供的示例,他以为成功在望,因为示例中不同网站可以互不干扰。然而,实际操作起来,问题却一个接一个。

开发这一过程,会遇到不少代码难题。由于缺乏相关经验,诸多事项需从头开始探索。在搜集资料、修正代码的过程中,时间悄然流逝,精力也在持续消耗。

搜索与趟坑

初次搜索解决方案时,搜索结果呈现了答案,但当时并未意识到这些信息的价值。经过一番曲折,才意识到先前忽略的部分才是最珍贵的。在探索过程中,不断跨越一个又一个代码难题。有时是逻辑上的错误,有时是语法上的小疏忽,这些错误耗费了我大量时间去排查。

每次以为找到了对策,结果操作时却问题频发,挫败感不断累积。于是,我调整心态,重新寻找出错的地方,反复尝试各种可能性。

关键实现

直接引入了必要的核心代码。代码页面涵盖了点击切换浏览器代码以及主程序启动时的初始化代码等。每一行代码都凝聚了多次试验的成果。编写这些代码时,必须保证各项功能的正常运作,并持续检验其稳定性。

/// 

        /// 初始化浏览器集合
        /// 

        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;
            }
        }

精心编排代码逻辑,努力优化代码架构,目的都是为了使程序运行得更加出色。即便如此,即便在取得一定进展后,仍然面临着更多挑战。

<Border Grid.Row="1" BorderBrush="Transparent" Background="#f0f0f0" BorderThickness="0" >
<Grid x:Name="MainGrid"/>
            

优化程序

WPF的数据驱动挺受欢迎,而且对高DPI设备的支持也不错。但最初打包后的文件有300多兆,老板对此难以接受。于是开始了漫长的优化过程。经过不懈努力,文件大小被压缩到了100兆以下。在这一过程中,我们不断尝试新的方法,对程序进行了精简。

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 + @"Pluginspepflashplayer.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;
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954046.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Shell 经典面试例题

1.shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 编写脚本&#xff1a; #!/bin/bash FILE"/tmp/size.log" if [ -f "$FILE" ]; then echo "文件存在&#xff0c;显示文件内容&…

移动云自研云原生数据库入围国采!

近日&#xff0c;中央国家机关2024年度事务型数据库软件框架协议联合征集采购项目产品名单正式公布&#xff0c;移动云自主研发的云原生数据库产品顺利入围。这一成就不仅彰显了移动云在数据库领域深耕多年造就的领先技术优势&#xff0c;更标志着国家权威评审机构对移动云在数…

Centos 宝塔安装

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 安装成功界面 宝塔说明文档 https://www.bt.cn/admin/servers#wcu 或者可以注册宝塔账号 1 快速部署 安装docker 之后 2 需要在usr/bin下下载do…

ros2笔记-6.2 使用urdf创建机器人模型

本节主要跟着小鱼老师的视频操作&#xff0c;不同的仿真平台有不同的建模语言&#xff0c;但是几乎都支持URDF。 本节使用URDF创建一个机器人模型。 6.2.1 帮机器人创建一个身体 URDF使用XML来描述机器人的结构和传感器、执行器等信息。 在chapt6/chap6_ws/src创建功能包:r…

文章复现—面向配电网韧性提升的移动储能预布局与动态调度策略

目录 一、主要内容&#xff1a; 二、实际运行效果&#xff1a; 三、文章介绍&#xff1a; 四、完整代码数据下载&#xff1a; 一、主要内容&#xff1a; &#xff08;matlab代码&#xff09;该程序复现《面向配电网韧性提升的移动储能预布局与动态调度策略》&#xff0c;具…

【ASP.NET学习】Web Forms创建Web应用

文章目录 什么是 Web Forms&#xff1f;ASP.NET Web Forms - HTML 页面用 ASP.NET 编写的 Hello RUNOOB.COM它是如何工作的&#xff1f;经典 ASP ASP.NET Web Forms - 服务器控件经典 ASP 的局限性ASP.NET - 服务器控件ASP.NET - HTML 服务器控件ASP.NET - Web 服务器控件ASP.N…

python-leetcode-旋转图像

48. 旋转图像 - 力扣&#xff08;LeetCode&#xff09; class Solution:def rotate(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""n len(matrix)# 矩阵转置for i in range(n):for…

GPT 系列论文精读:从 GPT-1 到 GPT-4

学习 & 参考资料 前置文章 Transformer 论文精读 机器学习 —— 李宏毅老师的 B 站搬运视频 自监督式学习(四) - GPT的野望[DLHLP 2020] 來自猎人暗黑大陆的模型 GPT-3 论文逐段精读 —— 沐神的论文精读合集 GPT&#xff0c;GPT-2&#xff0c;GPT-3 论文精读【论文精读】…

《计算机网络》课后探研题书面报告_了解PPPoE协议

PPPoE协议的工作原理与应用分析 摘 要 PPPoE&#xff08;Point-to-Point Protocol over Ethernet&#xff09;是一种广泛应用于宽带接入的网络协议&#xff0c;特别是在DSL&#xff08;数字用户线路&#xff09;和光纤网络中具有重要的应用价值。PPPoE结合了PPP协议的认证、加…

玩转大语言模型——langchain调用ollama视觉多模态语言模型

系列文章目录 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 langchain调用ollama视觉多模态语言模型 系列文章目录前言使用Ollama下载模型查找模型下载模型 测试模型ollama测试langchain测试加载图片加载模型…

开始使用Panuon开源界面库环境配置并手写VS2019高仿界面

1. Panuon环境配置 1.1. 通过Nuget 安装 Panuon.WPF.UI1.2. xaml引用命名空间1.3. using Panuon.WPF.UI; 2. VS2019 view 2.1. 设置窗体尺寸和title2.2. 添加静态资源 2.2.1. 什么是静态资源 2.3. 主Grid 2.3.1. 盒子模型2.3.2. 嵌套布局 3. 总结 1. Panuon环境配置 1.1. 通…

[Git] 深入理解 Git 的客户端与服务器角色

Git 的一个核心设计理念是 分布式&#xff0c;每个 Git 仓库都可以既是 客户端&#xff0c;也可以是 服务器。为了更好地理解这一特性&#xff0c;我们通过一个实际的 GitHub 远程仓库和本地仓库的场景来详细说明 Git 如何在客户端和服务器之间协作&#xff0c;如何独立地进行版…

基于考研概率论知识解读 Transformer:为何自注意力机制要除以根号 dk

Transformer自注意力机制中除以 d k \sqrt{d_k} dk​ ​深度剖析 【 Transformer 系列&#xff0c;故事从 d k \sqrt{d_k} dk​ ​说起】 LLM这么火&#xff0c;Transformer厥功甚伟&#xff0c;某天心血来潮~&#xff0c;再去看看&#xff01; 它长这个样子&#xff1a; 深入…

使用 selenium-webdriver 开发 Web 自动 UI 测试程序

优缺点 优点 有时候有可能一个改动导致其他的地方的功能失去效果&#xff0c;这样使用 Web 自动 UI 测试程序可以快速的检查并定位问题&#xff0c;节省大量的人工验证时间 缺点 增加了维护成本&#xff0c;如果功能更新过快或者技术更新过快&#xff0c;维护成本也会随之提高…

【Redis】初识分布式系统

目录 单机架构 分布式系统 应用数据分离架构 应用服务集群架构 读写分离/主从分离架构 冷热分离架构 垂直分库 微服务架构 分布式名词概念 本篇博文&#xff0c;将根据分布式系统的演进一步一步介绍每一种架构的形式&#xff0c;最后为大家总结了一些分布式中常用的…

微服务之松耦合

参考&#xff1a;https://microservices.io/post/architecture/2023/03/28/microservice-architecture-essentials-loose-coupling.html There’s actually two different types of coupling: runtime coupling - influences availability design-time coupling - influences…

pytest+request+yaml+allure搭建低编码调试门槛的接口自动化框架

接口自动化非常简单&#xff0c;大致分为以下几步&#xff1a; 准备入参调用接口拿到2中response&#xff0c;继续组装入参&#xff0c;调用下一个接口重复步骤3校验结果是否符合预期 一个优秀接口自动化框架的特点&#xff1a; 【编码门槛低】&#xff0c;又【能让新手学到…

基于Springboot + vue实现的文档管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Pycharm连接远程解释器

这里写目录标题 0 前言1 给项目添加解释器2 通过SSH连接3 找到远程服务器的torch环境所对应的python路径&#xff0c;并设置同步映射&#xff08;1&#xff09;配置服务器的系统环境&#xff08;2&#xff09;配置服务器的conda环境 4 进入到程序入口&#xff08;main.py&#…

初学stm32 --- II2C_AT24C02,向EEPROM中读写数据

目录 IIC总线协议介绍 IIC总线结构图 IIC协议时序 1. ACK&#xff08;Acknowledge&#xff09; 2. NACK&#xff08;Not Acknowledge&#xff09; IO口模拟II2C协议 发送起始信号&#xff1a; 发送停止信号&#xff1a; 检测应答信号&#xff1a; 发送应答信号&#x…