Visual Studio 发布程序自动更新 ClickOnce和AutoUpdater测试

文章目录

前言

虽然写的大部分都是不联网项目,上位机的项目一般写好了就不动了。但是说不定以后就需要自动更新呢。桌面程序不像网页,联网就能用。而是要进行版本号判断进行更新的。

运行环境

  • 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项目

xml 复制代码
<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>
csharp 复制代码
    /// <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# 自定义配置文件序列化生成+文件格式错误自动回档

csharp 复制代码
   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();
           }
           
       }
   }

自动更新代码封装

csharp 复制代码
  /// <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语言。

相关推荐
wjhx几秒前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
踏过山河,踏过海1 分钟前
【qt-查看对应的依赖的一种方法】
qt·visual studio
冰暮流星11 分钟前
javascript之二重循环练习
开发语言·javascript·数据库
万岳科技系统开发36 分钟前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
冉冰学姐1 小时前
SSM智慧社区管理系统jby69(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·管理系统·智慧社区·ssm 框架
杨超越luckly1 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
Elastic 中国社区官方博客1 小时前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
仍然.1 小时前
MYSQL--- 聚合查询,分组查询和联合查询
数据库
一 乐1 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
啦啦啦_99991 小时前
Redis-0-业务逻辑
数据库·redis·缓存