c# 如何实现自动更新程序

针对C#如何实现自动更新程序,一般有两种实现方式,分别是:

1.使用ClickOnce部署

ClickOnce是微软公司提供的一种快速、简单的部署技术,可以帮助开发人员轻松地完成应用程序的自动更新。其主要优点是使用简便、稳定性高、和Windows操作系统深度耦合。

其中实现步骤如下:

  • 首先,我们需要在Visual Studio中针对该应用程序进行发布设置,定义更新选项。
  • 点击“项目” → “发布” → 选择“发布向导”。
  • 下一步,选择“从我的计算机启动” → 点击“浏览”,选择保存位置
  • 设置“启动时检查更新”为“启动应用程序时” → 完成

完成之后,运行应用程序会在本地生成一个安装文件和一个应用程序清单,当用户运行此程序时,ClickOnce会自动检查更新,并提示用户更新。

2.使用自行编写更新器程序

另一种自动更新的方式是,我们自己编写一个软件更新程序,这种方法通常会在原程序首次安装时,安装一个检查更新的模块,或在原程序中加入检查更新的代码模块。当软件更新程序检测到当前版本不是最新版本时,自动下载并运行最新版本的安装程序。

具体实现步骤如下:

  • 在程序中实现检测更新的模块,并且定义更新的服务器地址。
  • 程序启动时,进行自动检查当前版本,如果更新,则下载最新的程序版本,并以静默方式安装。
  • 在应用程序内部实现原版本的卸载和最新版本的安装等操作,以达到自更新的目的。

这种方式可以使用各种语言来实现,例如使用C#编写更新程序,关键在于处理版本更新的逻辑。

下面是两种方式的示例程序:

  1. ClickOnce自动更新示例

这是Vistual Studio自带的点击一键发布实现自动更新的程序。需要创建一个应用程序,并发布运行后,会自动检测更新并更新。

https://docs.microsoft.com/zh-cn/visualstudio/deployment/how-to-publish-a-clickonce-application?view=vs-2019

  1. 自定义自动更新程序示例

下面是一个基于C#的自动更新程序的代码示例,主要实现了检测软件版本、更新程序下载、卸载旧版本、安装新版本等功能。

using System;
using System.ComponentModel;
using System.Net;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Diagnostics;

namespace AutoUpdater
{
    public class UpdateManager
    {
        private readonly string _appName;
        private readonly string _appDir;
        private readonly string _updateUrl;

        private readonly BackgroundWorker _worker;

        public UpdateManager(string appName, string appDir, string updateUrl)
        {
            _appName = appName;
            _appDir = appDir;
            _updateUrl = updateUrl;

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true,
            };
            _worker.DoWork += OnDoWork;
            _worker.ProgressChanged += OnProgressChanged;
            _worker.RunWorkerCompleted += OnCompleted;
        }

        public void StartUpdateIfNeeded()
        {
            if (!_worker.IsBusy)
            {
                _worker.RunWorkerAsync();
            }
        }

        private void OnDoWork(object sender, DoWorkEventArgs e)
        {
            var progress = 0;
            var state = "";
            var version = GetLastestVersion(ref progress, ref state);
            if (version == null) return;

            if (version > Assembly.GetExecutingAssembly().GetName().Version)
            {
                DownloadAndInstallVersion(version, ref progress, ref state);
            }
        }

        private Version GetLastestVersion(ref int progress, ref string state)
        {
            progress = 10;
            state = "正在检查更新...";
            var req = WebRequest.Create(_updateUrl);
            req.Timeout = 15000;
            var resp = req.GetResponse();
            var mtime = resp.Headers["Last-Modified"];
            Version version = null;

            if (mtime != null && DateTime.TryParse(mtime, out var lastModified))
            {
                progress = 20;

                version = new Version(resp.Headers["Update-Version"]);
                if (version > Assembly.GetExecutingAssembly().GetName().Version)
                {
                    state = $"发现新的版本 {version}";
                    progress = 50;
                }
                else
                {
                    state = "当前是最新版本,不需要更新。";
                    progress = 100;
                }
            }

            return version;
        }

        private void DownloadAndInstallVersion(Version version, ref int progress, ref string state)
        {
            state = $"开始下载新的版本 {version}...";
            progress = 60;

            using (var client = new WebClient())
            {
                client.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.Now.ToString();
                client.DownloadProgressChanged += (s, e) => {
                    progress = 60 + e.ProgressPercentage * 4 / 5;
                    state = $"正在下载 {e.ProgressPercentage}%...";
                };
                var file = Path.Combine(_appDir, $"setup-{version}.exe");
                client.DownloadFile(new Uri($"{_updateUrl}/{version}"), file);

                state = $"下载完成,准备卸载旧版本并安装新版本...";
                progress = 90;
                var uninstaller = Path.Combine(_appDir, "uninstall.exe");
                if (File.Exists(uninstaller))
                {
                    Process.Start(uninstaller).WaitForExit();
                }

                Process.Start(file, "/VERYSILENT /SUPRESSMSGBOXES").WaitForExit();
            }

            state = "安装完成,请关闭程序重新打开。";
            progress = 100;
        }

        private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine($"[{DateTime.Now}] {e.ProgressPercentage}%: {e.UserState}");
        }

        private void OnCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // do something
        }
    }
}

该示例程序包含了自定义的UpdateManager类,用于检测程序是否存在更新。可以在所有涉及到更新检测的地方调用该类的StartUpdateIfNeeded()方法即可实现自动更新。其中需要手动在服务端实现版本号解析与传输等功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c# 如何实现自动更新程序 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • ASP.NET Core通用主机实现托管服务

    ASP.NET Core通用主机实现托管服务 在本攻略中,我们将详细讲解ASP.NET Core通用主机实现托管服务的技术及工作原理,并提供两个示例说明。 什么是ASP.NET Core通用主机 ASP.NET Core通用主机是一种用于托管ASP.NET Core应用程序的机制。通用主机可以帮助开发人员更好地组织和管理应用程序的代码,提高应用程序的可维护性…

    C# 2023年5月16日
    00
  • C#中ref关键字的用法

    当在C#中需要传递一个变量时,使用传值或传引用的方法。传值方式传递的是变量的值,而传递引用时传递的是变量的地址。ref关键字可以用来在函数调用中传递变量的地址,此时函数内对该变量的任何修改都会影响到调用者。 下面是ref关键字在C#中的用法示例: 1. 在函数中修改变量的值 假设我们有一个函数,要求增加输入值的值,可以使用ref关键字来传递变量,以便在函数中…

    C# 2023年5月31日
    00
  • Jquery+asp.net后台数据传到前台js进行解析的方法

    在ASP.NET中,可以使用JQuery将后台数据传递到前台JavaScript进行解析。本文将提供详解如何使用JQuery+ASP.NET后台数据传到前台JavaScript进行解析的完整攻略,包括在ASP.NET中使用JQuery、在后台代码中获取数据、在前台JavaScript中解析数据等。同时,本文还提供两个示例,演示如何使用JQuery+ASP.N…

    C# 2023年5月15日
    00
  • ASP.NET Core MVC中的标签助手(TagHelper)用法

    接下来我会给出关于“ASP.NET Core MVC中的标签助手(TagHelper)用法”的详细讲解。 什么是标签助手? 标签助手(TagHelper)是AspNet Core MVC 框架中一项非常有用的功能,它可以让我们简化开发工作。它能够提高视图页面的代码可读性和重用性,并且可以减少我们的代码量。它主要通过HTML标签来处理视图中的数据。在视图中,标…

    C# 2023年6月3日
    00
  • C#中List存放元素的工作机制

    C#中的List\是一个动态数组,可以根据需要自动扩充长度以存放更多元素,其中的T代表元素的类型。List\在内存中的存储方式是连续的一段内存空间,这也就意味着List\能够像数组一样快速地寻址访问元素,同时也具有动态扩容的能力。 当向List\中添加元素时,会先检查当前List\的容量是否足够,若不足则会申请一块新的连续内存,将原来的元素复制到新的内存空间…

    C# 2023年6月6日
    00
  • C#中comboBox实现三级联动

    下面我来详细讲解C#中如何使用comboBox实现三级联动。 实现思路 三级联动是指在页面中有三级选项,当第一级选项发生变化时,第二级选项和第三级选项的内容会随之改变。在C#中,我们可以利用comboBox控件的SelectedIndexChanged事件和Add方法来实现三级联动。 首先,在设计表单时,我们需要创建三个comboBox控件,分别用来显示三级…

    C# 2023年6月1日
    00
  • C# DirectoryInfo.GetDirectories – 获取目录下的所有子目录信息

    C# 中的 DirectoryInfo 类提供了多种用于操作目录的方法,其中 GetDirectories 方法用于获取指定目录中的所有子目录。 方法作用 DirectoryInfo.GetDirectories 方法返回指定目录中的所有子目录的数组,该数组的元素为 DirectoryInfo 类型,可以通过该类型实例调用其它目录操作方法。 方法使用方法 语…

    C# 2023年4月19日
    00
  • C#实现简单屏幕监控的方法

    当我们需要监控并获取系统正在运行的一些信息时,屏幕监控便是一种非常有效的手段。在C#语言中,我们可以通过System.Windows.Forms这个库来实现简单的屏幕监控。 获取屏幕上的图像数据 第一步是获取屏幕上的图像数据。我们可以使用Screen类来获取当前屏幕的宽、高等参数,然后通过Graphics类的CopyFromScreen方法将屏幕上的图像数据…

    C# 2023年6月6日
    00
合作推广
合作推广
分享本页
返回顶部