当前位置: 首页 > news >正文

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 使用简介

在这里插入图片描述

在这里插入图片描述

实现原理

IIS
Update.html:更新日志详细信息的内容
AutoUpdateStarter.xml:版本号信息
Update.zip:程序压缩包,覆盖式安装

简单使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

新建一个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&#xff08;Visual Studio 程序发布&#xff09;IIS新建文件夹C# 控制台测试安装测试更新测试卸载 AutoUpdaterDotNET实现原理简单使用新建一个WPF项目 代码封装自动更新代码封装简单使用 总结 前言 虽然写的大部分都是不联网项目&#xff0c;…...

Codeforces Round 761 (Div. 2) E. Christmas Chocolates(思维题 树的直径 二进制性质 lca)

题目 n(n<2e5)个值&#xff0c;第i个值ai(0<ai<1e9)&#xff0c;所有ai两两不同 初始时&#xff0c;选择两个位置x,y(x≠y)&#xff0c;代表需要对这两个位置进行操作&#xff0c;要把其中一个值变成另一个 你可以执行若干次操作&#xff0c;每一次&#xff0c;你可…...

知识图谱之汽车实战案例综述与前瞻分析

知识图谱的前置介绍 什么是知识图谱 知识图谱本质(Knowledge Graph&#xff09;上是一种叫做语义网络(semantic network &#xff09; 的知识库&#xff0c;即具有有向图结构的一个知识库&#xff1b;图的结点代表实体&#xff08;entity&#xff09;或者概念&#xff08;con…...

网关Gateway

什么是网关? 网关实质上是一个网络通向其他网络的 IP 地址&#xff0c;是当前微服务项目的"统一入口"。 网关能做什么&#xff1f; 反向代理 、鉴权、 流量控制、 熔断、 日志监控等 图片原文&#xff1a;http://t.csdnimg.cn/SvUJh 核心概念 Router&#xff08;…...

java 生成一个当前时间的时间搓

开发过程中 用时间搓数值格式存储 会更加精准 那么 我们在一些日常增删查改中就可以用时间搓来记录操作时间 就一行代码 long timestamp System.currentTimeMillis();他就能生成当前时间的时间搓 运行结果如下 然后 我们可以在 http://shijianchuo.wiicha.com/ 上进行转换查…...

金融中IC和IR的定义

当谈到金融领域时&#xff0c;IC&#xff08;Information Coefficient&#xff09;和IR&#xff08;Information Ratio&#xff09;通常是用来评估投资组合管理绩效的指标。它们都涉及到投资者对信息的利用和管理的效果。 信息系数&#xff08;IC - Information Coefficient&a…...

Git(2):Git环境的安装

本教程里的git命令例子都是在Git Bash中演示的&#xff0c;会用到一些基本的linux命令&#xff0c;在此为大家提前列举&#xff1a; ls/ll 查看当前目录cat 查看文件内容touch 创建文件vi vi编辑器&#xff08;使用vi编辑器是为了方便展示效果&#xff0c;学员可以记事本、edi…...

Pytest单元测试系列[v1.0.0][pytest插件常用技巧]

使用pytest-xdist并发执行测试 pytest-xdist&#xff1a;Run Tests in Parallel [https://pypi.python.org/pypi/pytest-xdist] 在自动化测试中有些资源只能同时被一个测试用例访问&#xff0c;如果不需要同时使用同一个资源&#xff0c;那么测试用例便可以并行执行 执行命令…...

嵌入式培训机构四个月实训课程笔记(完整版)-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引导&#xff1a; 1、Linux开机启动的完整过程&#xff1a; 2、bios的作用&#xff1a; 3、boot&#xff1a; 4.mbr: 5、grub&#xff1a; 6、加载内核文件&#xff1a; 7、启动进程&#xff1a; 8、centos6与centos7的区别&#xff1a; 9、完整的过程 …...

HarmonyOS 应用开发学习笔记 ets自定义组件及其引用 @Component自定义组件

Component注解的作用是用来构建自定义组件 Component组件官方文档 自定义组件具有以下特点&#xff1a; 可组合&#xff1a;允许开发者组合使用系统组件、及其属性和方法。 可重用&#xff1a;自定义组件可以被其他组件重用&#xff0c;并作为不同的实例在不同的父组件或容器…...

在做题中学习(43):长度最小的子数组

LCR 008. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;同向双指针-------滑动窗口算法 解释&#xff1a;本是暴力枚举做法&#xff0c;因为全部是正整数&#xff0c;就可以利用单调性和双指针解决问题来节省时间 思路&#xff1a; 如上面图&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. 很多组织和机构都想在元宇宙的定义上掌握话语权&#xff0c;使得它的定义中存在矛盾之处&#xff0c;也有大量含义混淆之处 1.1. 微软 1.1.1. 在谈论“多个元宇宙” 1.1.2. 微软首席执行官萨提亚纳德拉将元宇宙描述为一种可以将“整个…...

听GPT 讲Rust源代码--compiler(2)

File: rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_codegen_cranelift/build_system/prepare.rs文件的作用是为Cranelift代码生成器构建系统准备依赖项。 具体来说&#xff0c;该文件的主要目标是处理Crane…...

SpringCloud系列篇:核心组件之负载均衡组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.负载均衡组件是什么 二.负载均衡…...

多线程模板应用实现(实践学习笔记)

出处&#xff1a;B站码出名企路 个人笔记&#xff1a;因为是跟着b站的教学视频以及文档初步学习&#xff0c;可能存在诸多的理解有误&#xff0c;对大家仅供借鉴&#xff0c;参考&#xff0c;然后是B站up阳哥的视频&#xff0c;我是跟着他学。大家有兴趣的可以到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…...

既然有 HTTP 协议,为什么还要有 RPC?

HTTP 和 RPC 都能解决网络通信问题&#xff0c;但它们的设计初衷和适用场景截然不同。简单来说&#xff0c;HTTP 是为了通用性和跨平台设计的&#xff08;像万能的集装箱&#xff09;&#xff0c;而 RPC 是为了极致的性能和开发效率设计的&#xff08;像工厂内部的高速流水线&a…...

STM32模拟Linux内核自动初始化机制实现

STM32模拟Linux内核自动初始化机制实现1. 项目概述1.1 技术背景在传统嵌入式开发中&#xff0c;程序通常按照顺序逻辑执行&#xff0c;当系统复杂度增加时会导致代码臃肿、模块耦合紧密。Linux内核通过initcall机制实现了模块化初始化&#xff0c;本项目在STM32平台上模拟实现了…...

零基础玩转luci-app-unblockneteasemusic完全指南:从安装到多设备协同的3步进阶法

零基础玩转luci-app-unblockneteasemusic完全指南&#xff1a;从安装到多设备协同的3步进阶法 【免费下载链接】luci-app-unblockneteasemusic [OpenWrt] 解除网易云音乐播放限制 项目地址: https://gitcode.com/gh_mirrors/lu/luci-app-unblockneteasemusic luci-app-u…...

不用下载IDE!浏览器直接练Python二级考题的宝藏网站测评

浏览器直通Python二级考场&#xff1a;零配置备考实战指南 距离全国计算机二级Python考试还有30天&#xff0c;小张的笔记本电脑却突然罢工。维修店报价让他望而却步&#xff0c;而图书馆公共电脑禁止安装软件的规定更让他雪上加霜。这种困境并非个例——据教育技术协会2024年…...

如何快速掌握终端数字雨效果:完整跨平台配置指南

如何快速掌握终端数字雨效果&#xff1a;完整跨平台配置指南 【免费下载链接】cmatrix Terminal based "The Matrix" like implementation 项目地址: https://gitcode.com/gh_mirrors/cm/cmatrix 想在终端中重现《黑客帝国》电影里的经典数字雨场景吗&#xf…...

Python开源代码管理避坑实战:从Git高级操作到Docker环境配置

前言&#xff1a;为什么你总在开源门前徘徊&#xff1f; “这个项目看起来好复杂&#xff0c;我连代码都看不懂...” “提交PR会不会被大佬嘲笑&#xff1f;” “环境配置又报错了&#xff0c;算了&#xff0c;下次再说吧” 如果你有过这些想法&#xff0c;别担心&#xff…...

42-西门子1200伺服控制5轴程序 程序采用1200系列PLC,项目实现以下功能: (1)

42-西门子1200伺服控制5轴程序 程序采用1200系列PLC&#xff0c;项目实现以下功能&#xff1a; &#xff08;1&#xff09;.三轴机械手联动取放料PTO脉冲定位控制台达B2伺服 &#xff08;2&#xff09;.台达伺服速度模式应用扭矩模式应用实现收放卷 &#xff08;3&#xff09;.…...

FireRedASR Pro模型架构浅析:从卷积神经网络到端到端设计

FireRedASR Pro模型架构浅析&#xff1a;从卷积神经网络到端到端设计 最近在语音识别圈子里&#xff0c;FireRedASR Pro这个名字被提到的次数越来越多了。不少朋友都在问&#xff0c;这个模型到底有什么特别之处&#xff0c;为什么大家都在讨论它。其实&#xff0c;它的核心魅…...

LVGL字体扩展避坑指南:freetype缓存管理导致的内存泄漏问题排查实录

LVGL字体扩展深度解析&#xff1a;如何规避freetype缓存管理中的内存泄漏陷阱 在嵌入式GUI开发中&#xff0c;LVGL结合freetype的动态字体加载功能为多语言支持提供了强大支持&#xff0c;但这也带来了内存管理的复杂性。本文将深入探讨一个典型场景&#xff1a;当项目需要频繁…...

SPIRAN ART SUMMONER跨平台适配:Windows/macOS/Linux下Streamlit祭坛兼容性

SPIRAN ART SUMMONER跨平台适配&#xff1a;Windows/macOS/Linux下Streamlit祭坛兼容性 1. 引言&#xff1a;当幻光祭坛遇见不同操作系统 想象一下&#xff0c;你刚刚在网络上看到了一个令人惊叹的AI图像生成工具——SPIRAN ART SUMMONER。它那充满《最终幻想10》风格的“幻光…...