winform发布功能附加dll、db、xml、json等文件

news2024/11/16 22:55:52

我们日常进行程序的更新升级可能会用到winform的发布功能,但有些文件可能会无法伴随着发布一同发布出去或者每次发布后文件的数据被覆盖,下面一起看一下怎么解决:

winform发布功能参考我另一篇文章https://blog.csdn.net/qq_39569480/article/details/127212245

仅限于读的文件:

这里我们以json文件为例,在项目中创建json文件,保存时以utf-8格式保存https://blog.csdn.net/qq_39569480/article/details/119610914 ,有一点需要注意这里创建的文件虽然可以同发布一同将文件发布出去,使用时仅限于读取,如果在程序运行过程中写入json文件,在下次程序升级时会覆盖原来写入的内容。
在这里插入图片描述
文件属性选择
在这里插入图片描述
右键项目属性——发布——应用程序文件,找到创建的文件选择包括,这样在发布时文件会同程序一同发布。
在这里插入图片描述

可读可写的文件

如果想发布可读可写的文件我们需要换一个思路,如果直接通过项目发布在程序运行时写入文件数据后,如果程序下次升级会重新覆盖这个文件之前写入的数据就会被覆盖掉。

第一种思路可以在程序中增加一个文件,在程序首次运行时检测本地有没有此文件如果没有则复制程序目录下的文件到本地指定文件夹,我们以后对这个文件进行操作。

第二种思路我们在程序启动时检测本地有无文件,没有文件则创建文件,动态的数据存在这个新创建的文件中,
每次读写这个新创建的文件

在程序的load事件中检测有无文件,没有则创建

if (!Directory.Exists(@"C:\SetUp")) Directory.CreateDirectory(@"C:\SetUp");
try
            {
                string FilePath = $@"C:\SetUp\appsettings.xml";
                XmlDocument xmlDoc = new XmlDocument();
                if (File.Exists(FilePath))
                {
                    xmlDoc.Load(FilePath);

                    XmlNode 二级 = xmlDoc.SelectSingleNode($"Configure/{InstrumentName}");
                    if (二级 == null)
                    {
                        XmlNode memberlist = xmlDoc.SelectSingleNode($"Configure");
                        XmlElement lq = xmlDoc.CreateElement(InstrumentName);
                        memberlist.AppendChild(lq);
                    }

                    //读取节点数据
                    if (二级 != null)
                    {
                        //二级.RemoveAll();
                        XmlNode node1 = xmlDoc.SelectSingleNode($"Configure/{InstrumentName}/SqlServerInstanceName");
                        if (node1 != null) 二级.RemoveChild(node1);
                        XmlNode node2 = xmlDoc.SelectSingleNode($"Configure/{InstrumentName}/SqlServerDataBaseName");
                        if (node2 != null) 二级.RemoveChild(node2); 
                    }

                    XmlElement el1 = xmlDoc.CreateElement("SqlServerInstanceName");
                    el1.InnerText = InstanceName;
                    XmlElement el2 = xmlDoc.CreateElement("SqlServerDataBaseName");
                    el2.InnerText = DataBaseName; 

                    XmlNode 二级节点 = xmlDoc.SelectSingleNode($"Configure/{InstrumentName}");
                    二级节点.AppendChild(el1); 二级节点.AppendChild(el2);  

                    xmlDoc.Save(FilePath);
                }
                else
                {
                    //加入XML的声明段落,Save方法不再xml上写出独立属性
                    xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null));
                    //加入根元素 
                    XmlElement root = xmlDoc.CreateElement("Configure");
                    xmlDoc.AppendChild(root);

                    XmlElement memberlist = xmlDoc.CreateElement($"{InstrumentName}");

                    XmlElement el1 = xmlDoc.CreateElement("SqlServerInstanceName");
                    el1.InnerText = InstanceName;
                    XmlElement el2 = xmlDoc.CreateElement("SqlServerDataBaseName"); 

                    memberlist.AppendChild(el1); memberlist.AppendChild(el2);  

                    root.AppendChild(memberlist);
                    xmlDoc.Save(FilePath);
                }
                bool Result = ReadLocalSetUpFile();
                if (Result) MessageBox.Show("配置成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

db文件

数据库文件或者其它文件同上原理,我们先将文件放在项目中,属性选择始终复制,生成操作为内容,这样发布时会同程序一同发布
在这里插入图片描述
在这里插入图片描述
然后在程序运行时将文件拷贝至本地的指定路径

string ApplicationPath = Application.StartupPath;
string LocalDirectory=@"C:\";
string FilePath = $@"{LocalDirectory}MicrosoftStorage";

            if (!Directory.Exists(LocalDirectory)) Directory.CreateDirectory(LocalDirectory);
            if (!File.Exists(FilePath)) File.Copy($"{ApplicationPath}\\MicrosoftStorage", $@"{LocalDirectory}MicrosoftStorage", true);//允许覆盖目的地的同名文件

复制到指定文件夹后以后我们只需要读取本地的文件即可,这样每次发布升级就不会受影响

到这里可能大家还会有疑问,如果这个数据库以后有字段的新增修改怎么办呢?这里给大家提供一个思路:
首先我们可以在程序中创建一个文件,文件中记录所有表和字段的内容,程序每次升级时检测文件中的字段或表是否与数据库的表字段一致,不一致则新增
在这里插入图片描述
检测字段方法
可参考我另一篇文章检测sqlite字段是否存在https://blog.csdn.net/qq_39569480/article/details/128465934

private void CheckField()
        {
            try
            {
                List<FieldSetUpModel> Fields = new List<FieldSetUpModel>();
                using var streamReader = new StreamReader(@"Menu\Field.json", Encoding.UTF8);
                string FieldJson = streamReader.ReadToEnd();
                Fields = JsonConvert.DeserializeObject<List<FieldSetUpModel>>(FieldJson);

                FieldSetUpModel TableSetUp = new FieldSetUpModel();
                if (InstrumentName == "Excel文件") TableSetUp = Fields.Where(a => a.InstrumentName.Contains(InstrumentName) && a.Type == InstrumentType)?.FirstOrDefault();
                else TableSetUp = Fields.Where(a => a.InstrumentName.Contains(InstrumentName))?.FirstOrDefault();

                string[] FieldArray = TableSetUp.Fileds.Split(',');
                string TableName = TableSetUp.TableName;
                string LocalDB = $"{LocalDirectory}MicrosoftStorage";
                var (FieldCheckResult, FieldMsg) = _checkField.CheckFieldPresenceOrNot(TableName, FieldArray, _DB, LocalDB);
                if (!FieldCheckResult) MessageBox.Show("检查新增本地库表和字段时出现异常!请联系管理员");
            }
            catch (Exception e)
            {
                Log.Error($"检查新增本地数据库字段时失败:{e.Message + e.StackTrace + e.InnerException}");
                throw;
            }
        }
         public class FieldSetUpModel
    {
        public string InstrumentName { get; set; }
        public string Type { get; set; }
        public string TableName { get; set; }
        public string Fileds { get; set; }
    }
public (bool, string) CheckFieldPresenceOrNot(string TableName,string[] Field, DBConnHelper DB,string LocalDBPath) {
            using (IDbConnection db = DB.DBConnection("Sqlite", "", LocalDBPath, ""))
            {
                try
                {
                    string TableSql = $"select count(*) from sqlite_master where type='table' and name='{TableName}' ";
                    int ExistTable= db.ExecuteScalar<int>(TableSql);
                    if (ExistTable<1)
                    {//表不存在则新增表
                        List<string> NeedAddField = new List<string>();
                        for (int i = 0; i < Field.Length; i++)
                        {
                            NeedAddField.Add($"{Field[i]} TEXT");
                        }
                        string FieldStr = string.Join(",", NeedAddField);
                        string AddTableSql = $"create table {TableName}({FieldStr})";
                        db.Execute(AddTableSql);
                        string CreateAfter = $"select count(*) from sqlite_master where type='table' and name='{TableName}'";

                        bool TableAddResult = db.ExecuteScalar<int>(TableSql)>0;

                        if (!TableAddResult) return (false, $"添加本地库新表时失败,请联系管理员");
                        else return (true, "");
                    }

                    List<string> FailureField = new List<string>();
                    for (int i = 0; i < Field.Length; i++)
                    {
                        string Sql = $"PRAGMA  table_info({TableName})";
                        List<TableStructureModel> TableStructure= db.Query<TableStructureModel>(Sql).ToList();
                        bool Exist= TableStructure.Where(a=>a.name==Field[i]).ToList().Count()>0;
                        if (!Exist)
                        {//如果不存在则新增字段
                            string AddField = $"alter table {TableName} add column '{Field[i]}' TEXT";
                            bool EditResult= db.Execute(AddField)>0;
                            if (!EditResult)
                            {
                                FailureField.Add(Field[i]);
                            }
                        }
                    }
                    if (FailureField.Count>0)
                    {
                        string ErrorField= string.Join(",",FailureField);
                        return (false,$"添加本地库字段:{ErrorField}时失败,请联系管理员");
                    }
                    return (true,"");
                }
                catch (Exception ex)
                {
                    Log.Error($"检查新增本地数据表或库字段时失败:{ex.Message + ex.StackTrace + ex.InnerException}");
                    return (false,ex.Message);
                }
            }
        }
        public class TableStructureModel
    {
        public string cid { get; set; }
        public string name { get; set; }
        public string type { get; set; }
        public string notnull { get; set; }
        public string dflt_value { get; set; }
        public string pk { get; set; }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

筑基四层 —— 详解三子棋和扫雷

目录 一.修炼必备 二.三子棋详解 三.扫雷详解 四.三子棋和扫雷的完整代码 &#xff01;&#xff01;&#xff01;恭喜你&#xff0c;成功突破至筑基四层&#xff01;&#xff01;&#xff01; 一.修炼必备 1.入门必备&#xff1a;VS2019社区版&#xff0c;下载地址&#xff…

leetcode51,52 N皇后相关(回溯方法)

题目1&#xff1a;N皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题…

入职一年,那个准的下班的人,比我先升职了...

最近心态崩了。 和我同期一道进公司的人又升了一级&#xff0c;可是明明大家在进公司时&#xff0c;他不论是学历还是工作经验&#xff0c;样样都不如自己&#xff0c;眼下不过短短的两年时间便一跃在自己的职级之上&#xff0c;这着实让我有几分不甘心。 我想不明白&#xff…

谈谈Linux epoll惊群问题的原因和解决方案

近期排查了一个问题&#xff0c;epoll惊群的问题&#xff0c;起初我并不认为这是惊群导致&#xff0c;因为从现象上看&#xff0c;只是体现了CPU不均衡。一共fork了20个Server进程&#xff0c;在请求负载中等的时候&#xff0c;有三四个Server进程呈现出比较高的CPU利用率&…

OpenCV 图像平滑处理

本文是OpenCV图像视觉入门之路的第10篇文章&#xff0c;本文详细的在图像上面进行了图像均值滤波、方框滤波 、高斯滤波、中值滤波、双边滤波、2D卷积等操作。 OpenCV 图像平滑处理目录 1 均值滤波 2 方框滤波 3 高斯滤波 4 中值滤波 5 双边滤波 6 2D卷积(自定义…

电子技术——分立MOS放大电路

电子技术——分立MOS放大电路 有了前两节的学习&#xff0c;即三种放大器配置和偏置方法之后&#xff0c;我们可以通过现成的分立晶体管、电阻、电容等搭建分立MOS放大电路。 DC偏置基本结构 在本节我们选用的DC偏置基本结构是如图所示的源极恒流源的偏置方案&#xff0c;下图…

用#define宏实现Add函数

✋作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;C语言 我们知道#define宏是一种非常暴力的替换&#xff0c;宏定义会在程序编译预处理阶段在调用宏的位置进行文本内容的直接替换&#xff0c;因此我们在使用宏定义实现Add加法函数时就要注意一些可能会报错的问题。 …

第九层(10):STL之函数对象

文章目录前情回顾函数对象概念特点谓词概念内建函数对象分类算术仿函数关系仿函数逻辑仿函数下一座石碑&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;一名大一的智能制造专业学生&#xff0c;在学习C/C的路上会越走越远&#xff0c;后面不定期更新有关C/C语法&a…

你是如何学习 Java 的?

每一个行业中能成为大佬的人&#xff0c;一定都有他自己一套具有独到见解的方法...... 这个问题我很有发言权&#xff0c;从刚毕业做Java实习生月薪2k&#xff0c;到现在干了5年Java开发月薪43k&#xff0c;一直都在保持不断学习的状态。以我个人的经验来看&#xff0c;一个程…

视频分割新范式:视频感兴趣物体实例分割 VOIS

1. 背景视频中物体分割是视频理解的基础算法&#xff0c;也是对淘宝商品视频分析和加工所依赖的重要能力。传统的视频分割任务一般分为两种类型&#xff1a;一种是VOS&#xff08;Video Object Segmentation&#xff09;&#xff0c;该任务需要在第一帧给出物体的初始分割标注&…

Linux系列 目录和文件管理

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 简介 本章重点 一.检查文本内容 ​编辑 1.cat命令——显示并…

MySQL分表查询之Merge存储引擎实现

概念介绍 MySQL 分表之后怎么进行联合查询&#xff1f;用有表数量限制的 union all&#xff0c;还是汇总到一张表再查询&#xff0c;亦或用Sphinx&#xff08; 高性能SQL全文检索引擎 &#xff09;&#xff1f; 在这篇文章里&#xff0c;介绍使用 Merge [mɜːrdʒ] 存储引擎…

浅读人月神话(2)

读书笔记&#xff1a;今日翻书浅读&#xff0c;从《为什么巴比伦塔会失败》开始至《干将莫邪》结束&#xff0c;巴比伦塔的建造对当下项目推进有广泛借鉴意义&#xff0c;今天这几个章节在PMBOK中有一些可以互相对照学习的内容&#xff0c;《为什么巴比伦塔会失败&#xff1f;》…

荔枝派 zero 使用 Jlink 调试

Jlink 所谓硬件版本&#xff0c;就是这个调试器的硬件是第几代&#xff0c;我手上的这个是 V8 所谓固件版本&#xff0c;就是这个调试器主芯片中内置的软件是什么版本&#xff0c;我刷入的是 J-Link ARM V8 compiled Nov 28 2014 13:44:46 所谓 Jlink 工具版本&#xff0c;就…

记录--原生 canvas 如何实现大屏?

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 可视化大屏该如何做&#xff1f;有可能一天完成吗&#xff1f;废话不多说&#xff0c;直接看效果&#xff0c;线上 Demo 地址 lxfu1.github.io/large-scree…。 看完这篇文章(这个项目)&#xff…

在线支付系列【13】微信支付之签名验签流程分析

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 文章目录前言签名生成签名验证总结前言 在上篇文档中&#xff0c;我们简单实现了对接微信支付的几个接口。了解到wechatpay-apache-httpclient框架自动实现了签名和验签&#xff0c;接下来跟踪下源码&a…

LeetCode-136. 只出现一次的数字

目录题目分析哈希集位运算题目来源 https://leetcode.cn/problems/single-number/ 题目分析 题目有个条件可谓相当重要&#xff0c;即凡重复的元素最多重复一次&#xff08;原话&#xff1a;给定一个非空整数数组&#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个…

详解Mybatis-Plus中分页插件PaginationInterceptor, MybatisPlusInterceptor在SpringBoot中的使用

文章目录1. 描述1.1 MybatisPlusInterceptor1.2 InnerInterceptor2. 实现2.1 不带条件的分页查询2.2 带条件的分页查询2.3 简述Page类3. 注意事项1. 描述 1.1 MybatisPlusInterceptor 我们在开发的过程中&#xff0c;经常会遇到分页操作&#xff0c;其分为逻辑分页和物理分页…

Gif动态图片如何用静图制作?教你静图合成动图的方法

gif动图如何制作&#xff1f;相信对于gif动图大家都不陌生&#xff0c;在平时的聊天软件中、公众号文章中都可以看到。那么&#xff0c;要如何制作gif动图呢&#xff1f;下面&#xff0c;就给教大家两个在线gif制作&#xff08;https://www.gif.cn/&#xff09;的方法&#xff…

综合案例【商品管理系统-Java基础版】(附完整源码)

Java语言的一个超级简易的商品管理系统&#xff0c;适合初学者练手 源码包无法上传至资源&#xff08;blog已经超级完整啦&#xff09;如果还是需要完整源码src包可私分享 目录1 项目分析1.1 用户模块&#xff08;普通用户、管理员用户&#xff09;1.1.1前端系统&#xff08;普…