Visual Studio 发布程序自动更新 ClickOnce和AutoUpdater测试
文章目录
- 前言
- 运行环境
- ClickOnce(Visual Studio 程序发布)
- IIS新建文件夹
- C# 控制台测试
- 安装测试
- 更新测试
- 卸载
 
- AutoUpdaterDotNET
- 实现原理
- 简单使用
- 新建一个WPF项目
 
- 代码封装
- 自动更新代码封装
- 简单使用
 
 
- 总结
前言
虽然写的大部分都是不联网项目,上位机的项目一般写好了就不动了。但是说不定以后就需要自动更新呢。桌面程序不像网页,联网就能用。而是要进行版本号判断进行更新的。
运行环境
- Visual Studio 2022
- .net core 8.0
- IIS
ClickOnce(Visual Studio 程序发布)
毕竟是微软官方的部署方式,应该是挺简单的
ClickOnce 安全性和部署
快速创建软件安装包-ClickOnce

 
IIS新建文件夹

C# 控制台测试
新建一个简单的控制台程序进行测试
 
 
 
 
 
 
 
 
 
 


 
安装测试

这里报错是因为没有签名。


 安装成功,但是默认路径是C盘,有点尬尴
Choose install path for ClickOnce application during setup

更新测试

 
 


卸载
直接卸载即可



AutoUpdaterDotNET
AutoUpdater.NET github 仓库地址
AutoUpdater.NET 使用简介


实现原理
简单使用

 
 
新建一个WPF项目
<Window x:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp1"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Grid><StackPanel><TextBlock Text="版本1.0.1"FontSize="50"Name="LabelVersion" /><Button Content="按钮"  FontSize="30" Click="Button_Click"/></StackPanel></Grid>
</Window>    /// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();AutoUpdateTest();}public void AutoUpdateTest(){Assembly assembly = Assembly.GetEntryAssembly();LabelVersion.Text = $"Current Version : {assembly.GetName().Version}";//显示版本号AutoUpdater.AppTitle = "升级更新";Thread.CurrentThread.CurrentCulture =Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("zh");AutoUpdater.LetUserSelectRemindLater = true;AutoUpdater.RemindLaterTimeSpan = RemindLaterFormat.Minutes;AutoUpdater.RemindLaterAt = 1;AutoUpdater.ReportErrors = true;DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromMinutes(2) };//定时去检测更新根据自己业务需求timer.Tick += delegate { AutoUpdater.Start("http://localhost:10911/Updates/AutoUpdaterStarter.xml"); };timer.Start();}private void Button_Click(object sender, RoutedEventArgs e){AutoUpdater.Start("http://localhost:10911/Updates/AutoUpdaterStarter.xml");}}




代码封装
这里用到了之前的代码
C# 自定义配置文件序列化生成+文件格式错误自动回档
   public class MyXmlConfigHelper<T>{public T Setting { get; set; }public string FileName { get; set; } = "MyConfig.xml";public string DirectoryPath{get{var regex = new Regex(@"\\(\w+)\.(\w+)$");return regex.Split(FullPath)[0];}}public string DebugPath { get => Directory.GetCurrentDirectory(); }public string FullPath { get => DebugPath + "\\" + FileName; }public bool IsFileExist { get => File.Exists(FullPath); }public bool IsDirectoryExist { get => Directory.Exists(DirectoryPath); }public Action<string> ShowMsg { get; set; } = (msg)=>Console.WriteLine(msg);public MyXmlConfigHelper(){}public MyXmlConfigHelper(string filename){FileName = filename;if (!IsDirectoryExist){DirectoryInfo directoryInfo = new DirectoryInfo(DirectoryPath);directoryInfo.Create();}}public MyXmlConfigHelper(T setting ,string filename):this(filename){Setting = setting;}/// <summary>/// 创建文件/// </summary>public void Init(){if(IsFileExist){try{Read();}catch (Exception ex){ShowMsg(ex.ToString());throw new Exception("文件读取失败!请确认是否配置文件格式是否正确");}}else{Write();}}/// <summary>/// 覆盖文件/// </summary>public void ReInit(){ShowMsg("正在覆盖配置文件:" + FullPath);Write();}/// <summary>/// 写入配置类/// </summary>private void Write(){ShowMsg("正在生成配置文件:" + FullPath);var xmlHelper = new XmlSerializer(typeof(T));using (StreamWriter xmlWriter = new StreamWriter(FullPath)){//去掉烦人的命名空间XmlSerializerNamespaces ns = new XmlSerializerNamespaces();ns.Add("", "");xmlHelper.Serialize(xmlWriter, Setting, ns);xmlWriter.Close();}}/// <summary>/// 读取配置类/// </summary>private void Read(){ShowMsg("正在读取配置文件:"+FullPath);var xmlHelper = new XmlSerializer(typeof(T));using (StreamReader xmlReader = new StreamReader(FullPath)){Setting = (T)xmlHelper.Deserialize(xmlReader);xmlReader.Close();}}}自动更新代码封装
/// <summary>/// 自动更新帮助类/// </summary>public class AutoUpdateHelper{/// <summary>/// 更新地址/// </summary>public string UpdateLogUrl { get => BaseUrl + "Updates/UpdateLog.html"; }/// <summary>/// 网路基本路径/// </summary>public string BaseUrl { get; set; } = "http://localhost:10911/";/// <summary>/// Xml配置地址/// </summary>public string AutoXmlUrl { get => BaseUrl + "Updates/AutoUpdaterStarter.xml"; }/// <summary>/// 文件下载地址/// </summary>public string DownLoadUrl { get => BaseUrl + "DownLoads/Update.zip"; }/// <summary>/// Xml配置生成类/// </summary>public MyXmlConfigHelper<AutoUpdaterXmlEntity> MyXmlConfigHelper { get; set; } = new MyXmlConfigHelper<AutoUpdaterXmlEntity>(@"AutoUpdater\AutoUpdaterStarter.xml");/// <summary>/// 版本号/// </summary>public string VersionNo{get{Assembly assembly = Assembly.GetExecutingAssembly();return assembly.GetName().Version.ToString();}}/// <summary>/// 自动更新默认配置,Updates放配置文件,DownLoads放zip/// </summary>public AutoUpdateHelper(){AutoUpdater.AppTitle = $"升级更新";AutoUpdater.LetUserSelectRemindLater = true;AutoUpdater.RemindLaterTimeSpan = RemindLaterFormat.Minutes;AutoUpdater.RemindLaterAt = 1;AutoUpdater.ReportErrors = true;}/// <summary>/// 修改IIS网络地址,Updates放配置文件,DownLoads放zip/// </summary>/// <param name="url"></param>public AutoUpdateHelper(string url):this(){this.BaseUrl = url;}/// <summary>/// 自动更新程序/// </summary>public void Update(){AutoUpdater.Start(AutoXmlUrl);}/// <summary>/// 创建AutoXml文件/// </summary>public void CreateAutoXmlFile(){AutoUpdaterXmlEntity autoUpdaterXmlEntity = new AutoUpdaterXmlEntity(){Version = VersionNo,DownLoadUrl = DownLoadUrl,UpdateLogUrl = UpdateLogUrl};MyXmlConfigHelper.Setting = autoUpdaterXmlEntity;MyXmlConfigHelper.ReInit();}}/// <summary>/// 配置文件对应实体/// </summary>[XmlRoot("item")]public class AutoUpdaterXmlEntity{[XmlElement("version")]public string Version { get; set; }[XmlElement("url")]public string DownLoadUrl { get; set; }[XmlElement("changelog")]public string UpdateLogUrl { get; set; }[XmlElement("mandatory")]public string Mandatory { get; set; } = "false";}
简单使用

 
 

总结
还是AutoHelper好使,简单好用。AutoHelper的UpdateLog.html就自己加描述了,就是简单的html语言。
相关文章:
 
Visual Studio 发布程序自动更新 ClickOnce和AutoUpdater测试
文章目录 前言运行环境ClickOnce(Visual Studio 程序发布)IIS新建文件夹C# 控制台测试安装测试更新测试卸载 AutoUpdaterDotNET实现原理简单使用新建一个WPF项目 代码封装自动更新代码封装简单使用 总结 前言 虽然写的大部分都是不联网项目,…...
Codeforces Round 761 (Div. 2) E. Christmas Chocolates(思维题 树的直径 二进制性质 lca)
题目 n(n<2e5)个值,第i个值ai(0<ai<1e9),所有ai两两不同 初始时,选择两个位置x,y(x≠y),代表需要对这两个位置进行操作,要把其中一个值变成另一个 你可以执行若干次操作,每一次,你可…...
 
知识图谱之汽车实战案例综述与前瞻分析
知识图谱的前置介绍 什么是知识图谱 知识图谱本质(Knowledge Graph)上是一种叫做语义网络(semantic network ) 的知识库,即具有有向图结构的一个知识库;图的结点代表实体(entity)或者概念(con…...
 
网关Gateway
什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址,是当前微服务项目的"统一入口"。 网关能做什么? 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文:http://t.csdnimg.cn/SvUJh 核心概念 Router(…...
 
java 生成一个当前时间的时间搓
开发过程中 用时间搓数值格式存储 会更加精准 那么 我们在一些日常增删查改中就可以用时间搓来记录操作时间 就一行代码 long timestamp System.currentTimeMillis();他就能生成当前时间的时间搓 运行结果如下 然后 我们可以在 http://shijianchuo.wiicha.com/ 上进行转换查…...
 
金融中IC和IR的定义
当谈到金融领域时,IC(Information Coefficient)和IR(Information Ratio)通常是用来评估投资组合管理绩效的指标。它们都涉及到投资者对信息的利用和管理的效果。 信息系数(IC - Information Coefficient&a…...
 
Git(2):Git环境的安装
本教程里的git命令例子都是在Git Bash中演示的,会用到一些基本的linux命令,在此为大家提前列举: ls/ll 查看当前目录cat 查看文件内容touch 创建文件vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、edi…...
Pytest单元测试系列[v1.0.0][pytest插件常用技巧]
使用pytest-xdist并发执行测试 pytest-xdist:Run Tests in Parallel [https://pypi.python.org/pypi/pytest-xdist] 在自动化测试中有些资源只能同时被一个测试用例访问,如果不需要同时使用同一个资源,那么测试用例便可以并行执行 执行命令…...
嵌入式培训机构四个月实训课程笔记(完整版)-Linux系统编程第五天-Linux消息共享内存练习题(物联技术666)
更多配套资料CSDN地址:点赞+关注,功德无量。更多配套资料,欢迎私信。 物联技术666_嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记-CSDN博客物联技术666擅长嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记,等方面的知识,物联技术666关注机器学习,arm开发,物联网,嵌入式硬件,单片机…...
 
04set注入专题/简单类型/数组/List/Set/Map/空字符串/null/特殊符号
1.1注入外部Bean 在之前使用的案例就是注入外部Bean的方式。 <!-- class属性声明要管理哪个类中的对象 property标签的name是提示set方法名ref标签指明注入的bean的id--><bean id"userServiceBean" class"com.powernode.spring6.service.UserService…...
Linux引导和服务管理
目录 一.Linux引导: 1、Linux开机启动的完整过程: 2、bios的作用: 3、boot: 4.mbr: 5、grub: 6、加载内核文件: 7、启动进程: 8、centos6与centos7的区别: 9、完整的过程 …...
 
HarmonyOS 应用开发学习笔记 ets自定义组件及其引用 @Component自定义组件
Component注解的作用是用来构建自定义组件 Component组件官方文档 自定义组件具有以下特点: 可组合:允许开发者组合使用系统组件、及其属性和方法。 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器…...
 
在做题中学习(43):长度最小的子数组
LCR 008. 长度最小的子数组 - 力扣(LeetCode) 解法:同向双指针-------滑动窗口算法 解释:本是暴力枚举做法,因为全部是正整数,就可以利用单调性和双指针解决问题来节省时间 思路: 如上面图&am…...
 
如何将 element-ui 中的 el-select 默认展开
<el-form-item label"藕粉桂花糖糕" prop"state" required><el-selectref"mySelect"v-model"form.state"style"width: 280px"placeholder"请选择"><el-option label"藕粉" :value"…...
 
Typora基本用法
文章目录 一、标题标题快捷键 二、段落1.换行2.分割线 三、文字显示1.字体2.上下标 四、列表1.无序列表2.有序列表3.任务列表 五、区块显示六、代码显示1.行内代码2.代码块 七、链接八、脚注九、图片插入十、表格十一、流程图十二、表情符号十三、数学公式的输入1.公式的插入①…...
 
读元宇宙改变一切笔记02_元素(上)
1. 很多组织和机构都想在元宇宙的定义上掌握话语权,使得它的定义中存在矛盾之处,也有大量含义混淆之处 1.1. 微软 1.1.1. 在谈论“多个元宇宙” 1.1.2. 微软首席执行官萨提亚纳德拉将元宇宙描述为一种可以将“整个…...
 
听GPT 讲Rust源代码--compiler(2)
File: rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs 在Rust源代码中,rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs文件的作用是为Cranelift代码生成器构建系统准备依赖项。 具体来说,该文件的主要目标是处理Crane…...
 
SpringCloud系列篇:核心组件之负载均衡组件
🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.负载均衡组件是什么 二.负载均衡…...
 
多线程模板应用实现(实践学习笔记)
出处:B站码出名企路 个人笔记:因为是跟着b站的教学视频以及文档初步学习,可能存在诸多的理解有误,对大家仅供借鉴,参考,然后是B站up阳哥的视频,我是跟着他学。大家有兴趣的可以到b站搜索。加油…...
Linux系统中MYSQL重置密码(针对root忘记密码)
⼀ .进⼊MySql配置⽂件中 vi /etc/my.cnf 在最后⼀⾏添加免密码登陆: skip-grant-tables :wq 保存退出 ⼆.重启MySql service mysql restart 或 systemctl restart mysqld.service 三. 登陆数据库 mysql -uroot -p 让输⼊密码直接回⻋就可以 四.修改MySql密码 use mysql…...
 
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
 
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
 
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
 
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
