WPF 手撸插件 四 插件在线更新Autoupdater.NET.Official

1、本文将使用Autoupdater.NET.Official对应用程序进行在线更新。具体效果如下图所示。示例下载地址:https://download.csdn.net/download/xingchengaiwei/89642250

2、我使用的是本机下载,IIS的部署不是本文的主要内容,需要各位大佬自己解决。

2.1、添加一个网站,我这里叫AutoUpdater。如下图。

2.2、在AutoUpdater网站添加FTP站点,如下图。

2.3、在网站中添加文件Index.html,代码如下。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>更新说明</title>
    </head>
    <body>
        <h1>程序更新</h1>
        <p>更新版本号1.2.0.0</p>
        <p>更新内容:</p>
        <p>1.修复了部分bug</p>
        <p>2.增加了部分新功能</p>
    </body>
</html>

 这个html文件就是显示在更新界面中的内容。

2.4、添加文件AutoUpdaterStarter.xml,内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<item>
  <version>1.2.0.0</version>
  <url>http://127.0.0.1:8080/Downloads/WPFIPluginDemo.zip</url>
  <changelog>http://127.0.0.1:8080/</changelog>
  <mandatory>false</mandatory>
</item>

可以使用我提供的示例中的AutoUpdaterXML.zip中的程序生成XML文件。

 2.5、创建文件夹Downloads,将需要更新的文件WPFIPluginDemo.zip放在此文件夹中。具体文件结构如下图。

3、WPF程序端文件。

3.1、首先在NuGet中添加Autoupdater.NET.Official,主要版本问题。我使用的是1.8.6。如下图。

3.2、在程序的适当位置添加 代码如下。下面的代码功能是每隔2秒进行一次更新检查。

            DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
            timer.Tick += delegate
            {
                AutoUpdater.Start("http://127.0.0.1:8080/AutoUpdaterStarter.xml");
                //启用错误报告
                AutoUpdater.ReportErrors = true;
                //设置zip解压路径
                AutoUpdater.InstallationPath = Environment.CurrentDirectory;
                //处理应用程序在下载完成后如何退出
                AutoUpdater.ApplicationExitEvent += AutoUpdater_ApplicationExitEvent;
                //自定义处理更新逻辑事件
                //AutoUpdater.CheckForUpdateEvent += AutoUpdaterOnCheckForUpdateEvent;
            };
            timer.Start();

3.3、AutoUpdater.CheckForUpdateEvent 事件可以自定义更新逻辑事件,通过这个事件我们可以自定义更新的界面等。

3.4、我的主体代码内容如下。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using AbstractionLayer;
using AutoUpdaterDotNET;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using Path = System.IO.Path;

namespace WPFIPluginDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Assembly assembly = Assembly.GetEntryAssembly();

            //SetAutoUpdater();
            DispatcherTimer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
            timer.Tick += delegate
            {
                AutoUpdater.Start("http://127.0.0.1:8080/AutoUpdaterStarter.xml");
                //启用错误报告
                AutoUpdater.ReportErrors = true;
                //设置zip解压路径
                AutoUpdater.InstallationPath = Environment.CurrentDirectory;
                //处理应用程序在下载完成后如何退出
                AutoUpdater.ApplicationExitEvent += AutoUpdater_ApplicationExitEvent;
                //自定义处理更新逻辑事件
                //AutoUpdater.CheckForUpdateEvent += AutoUpdaterOnCheckForUpdateEvent;
            };
            timer.Start();

            this.tbVersion.Text = $"{assembly.GetName().Version}";

            //AutoUpdater.Start("http://127.0.0.1:8080/AutoUpdaterStarter.xml");

            //开始监控指定文件
            //StartMonitoring(GetCurrentProgramPath() + "\\Plugins");
            //加载已存在的插件
            LoadPlugins(GetCurrentProgramPath() + "\\Plugins");
        }

        private void AutoUpdater_ApplicationExitEvent()
        {
            //Text = @"Closing application...";
            Thread.Sleep(5000);
            Environment.Exit(0);
        }

        private void AutoUpdaterOnCheckForUpdateEvent(UpdateInfoEventArgs args)
        {
            if (args.Error == null)
            {
                //检测到有可用的更新
                if (args.IsUpdateAvailable)
                {
                    MessageBoxResult messageBoxResult;
                    if (args.Mandatory.Value)
                    {
                        messageBoxResult =
                            MessageBox.Show(
                                $@"当前有一个新版本{{args.CurrentVersion}}可用.你正在使用版本{{args.InstalledVersion}}.点击确认开始更新\",
                                @"更新可用\", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                    else
                    {
                        messageBoxResult =
                            MessageBox.Show(
                                $@"当前有一个新版本{args.CurrentVersion}可用.你正在使用版本{args.InstalledVersion}.确认要更新吗?", @"更新可用",
                                MessageBoxButton.YesNo, MessageBoxImage.Information);
                    }

                    if (messageBoxResult.Equals(MessageBoxResult.Yes) || messageBoxResult.Equals(MessageBoxResult.OK))
                    {
                        try
                        {
                            //触发更新下载
                            if (AutoUpdater.DownloadUpdate(args))
                            {
                                //Application.Current.Shutdown();//允许应用程序在关闭前进行一些清理工作。
                                Environment.Exit(0);//则立即终止应用程序,不进行任何清理工作。
                            }
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.Message, e.GetType().ToString(), MessageBoxButton.OK, MessageBoxImage.Error);
                            Debug.WriteLine(e);
                            throw;
                        }
                    }
                    else
                    {
                        //MessageBox.Show(
                        //    $@"当前为最新新版本", @"更新可用",
                        //    MessageBoxButton.OK,
                        //    MessageBoxImage.Information);
                    }
                }
            }
            else
            {
                if (args.Error is WebException)
                {
                    MessageBox.Show(
                        @"连接更新服务器失败,请检查网络连接.",
                        @"更新检查失败", MessageBoxButton.OK, MessageBoxImage.Error);
                }
                else
                {
                    MessageBox.Show(args.Error.Message,
                        args.Error.GetType().ToString(), MessageBoxButton.OK,
                        MessageBoxImage.Error);
                }
            }
        }

        private void SetAutoUpdater()
        {

            AutoUpdater.LetUserSelectRemindLater = true;

            AutoUpdater.RemindLaterTimeSpan = RemindLaterFormat.Minutes;

            AutoUpdater.RemindLaterAt = 1;

            //若您不想在更新表单上显示“跳过”按钮,那个么只需在上面的代码中添加以下行即可。
            AutoUpdater.ShowSkipButton = false;

            //如果要同步检查更新,请在启动更新之前将Synchronous设置为true,如下所示。
            AutoUpdater.Synchronous = true;

            //若你们不想在更新表单上显示“以后提醒”按钮,那个么只需在上面的代码中添加以下一行即可。
            AutoUpdater.ShowRemindLaterButton = false;

            //如果要忽略先前设置的“以后提醒”和“跳过”设置,则可以将“强制”属性设置为true。它还将隐藏“跳过”和“稍后提醒”按钮。如果在代码中将强制设置为true,那么XML文件中的强制值将被忽略。
            AutoUpdater.Mandatory = false;

            //如果服务器xml文件的版本大于AssemblyInfo中的版本则触发CheckForUpdateEvent
            AutoUpdater.CheckForUpdateEvent += (args) =>
            {
                if (args.Error == null)
                {
                    //检测到有可用的更新
                    if (args.IsUpdateAvailable)
                    {
                        MessageBoxResult messageBoxResult;
                        if (args.Mandatory.Value)
                        {
                            messageBoxResult =
                                MessageBox.Show(
                                    $@"当前有一个新版本{{args.CurrentVersion}}可用.你正在使用版本{{args.InstalledVersion}}.点击确认开始更新\",
                                    @"更新可用\", MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                        else
                        {
                            messageBoxResult =
                                MessageBox.Show(
                                    $@"当前有一个新版本{args.CurrentVersion}可用.你正在使用版本{args.InstalledVersion}.确认要更新吗?", @"更新可用",
                                    MessageBoxButton.YesNo, MessageBoxImage.Information);
                        }

                        if (messageBoxResult.Equals(MessageBoxResult.Yes) || messageBoxResult.Equals(MessageBoxResult.OK))
                        {
                            try
                            {
                                //触发更新下载
                                if (AutoUpdater.DownloadUpdate(args))
                                {
                                    //Application.Current.Shutdown();//允许应用程序在关闭前进行一些清理工作。
                                    Environment.Exit(0);//则立即终止应用程序,不进行任何清理工作。
                                }
                            }
                            catch (Exception e)
                            {
                                MessageBox.Show(e.Message, e.GetType().ToString(), MessageBoxButton.OK,MessageBoxImage.Error);
                                Debug.WriteLine(e);
                                throw;
                            }
                        }
                        else
                        {
                            MessageBox.Show(
                                $@"当前为最新新版本", @"更新可用",
                                MessageBoxButton.OK,
                                MessageBoxImage.Information);
                        }
                    }
                }
                else
                {
                    if (args.Error is WebException)
                    {
                        MessageBox.Show(
                            @"连接更新服务器失败,请检查网络连接.",
                            @"更新检查失败", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                    else
                    {
                        MessageBox.Show(args.Error.Message,
                            args.Error.GetType().ToString(), MessageBoxButton.OK,
                            MessageBoxImage.Error);
                    }
                }
            };
        }

        /// <summary>
        /// 手动更新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnAutoUpdater_OnClick(object sender, RoutedEventArgs e)
        {
            AutoUpdater.Start("http://127.0.0.1:8080/AutoUpdaterStarter.xml");
        }
        /// <summary>
        /// 文件监视
        /// </summary>
        private FileSystemWatcher _fileWatcher;
        /// <summary>
        /// 开始监视文件夹
        /// </summary>
        /// <param name="directoryPath"></param>
        private void StartMonitoring(string directoryPath)
        {
            // 创建 FileSystemWatcher 实例
            _fileWatcher = new FileSystemWatcher();

            // 设置要监视的目录路径
            _fileWatcher.Path = directoryPath;

            // 设置要监视的更改类型(例如:修改、创建、删除)
            _fileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

            // 添加事件处理程序
            _fileWatcher.Changed += OnChanged;
            _fileWatcher.Created += OnChanged;
            _fileWatcher.Deleted += OnChanged;

            // 开启事件监听
            _fileWatcher.EnableRaisingEvents = true;

            Debug.WriteLine($"已开始监视文件夹: {directoryPath}");
        }

        /// <summary>
        /// 当文件夹中内容发生改变时触发时间
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            //Debug.WriteLine($"文件或文件夹发生变更: {e.FullPath},事件类型: {e.ChangeType}");
            if ((e.ChangeType & WatcherChangeTypes.Created) != 0)
            {
                if (File.Exists(e.FullPath))
                {
                    Debug.WriteLine("创建了文件");
                    LoadPlugins(GetCurrentProgramPath() + "\\Plugins");
                    Debug.WriteLine($"文件或文件夹发生变更: {e.FullPath},事件类型: {e.ChangeType}");

                }
                else
                {
                    Debug.WriteLine("创建了文件夹");
                }
            }
        }

        private bool IsDirectory(string path)
        {
            try
            {
                FileAttributes attr = File.GetAttributes(path);

                if ((attr & FileAttributes.Directory) ==FileAttributes.Directory)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                return false;
            }
        }
        /// <summary>
        /// 停止监视文件夹
        /// </summary>
        public void StopMonitoring()
        {
            if (_fileWatcher != null)
            {
                // 停止引发事件
                _fileWatcher.EnableRaisingEvents = false;

                // 清理资源
                _fileWatcher.Dispose();
                _fileWatcher = null;

                Debug.WriteLine("已停止监视文件夹");
            }
        }
        /// <summary>
        /// 点击加载插件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnSearchPlugins_OnClick(object sender, RoutedEventArgs e)
        {
            LoadPlugins(GetCurrentProgramPath()+"\\Plugins");
        }
        /// <summary>
        /// 获取当前程序集的路径
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentProgramPath()
        {
            // 获取当前执行的程序集
            var assembly = Assembly.GetEntryAssembly();

            // 获取程序集所在的路径
            var assemblyLocation = assembly.Location;

            // 获取程序集所在的目录
            var programPath = Path.GetDirectoryName(assemblyLocation);

            return programPath;
        }
        /// <summary>
        /// 插件列表
        /// </summary>
        public List<IPlugin> ListIPlugins = new List<IPlugin>();
        /// <summary>
        /// 加载指定插件
        /// </summary>
        /// <param name="pluginDirectory"></param>
        public void LoadPlugins(string pluginDirectory)
        {
            try
            {
                Dispatcher.BeginInvoke(new Action(delegate
                {
                    // 获取所有插件DLL
                    var pluginDlls = Directory.GetFiles(pluginDirectory, "*.exe", SearchOption.TopDirectoryOnly);

                    foreach (var dll in pluginDlls)
                    {
                        try
                        {

                            Assembly pluginAssembly = Assembly.LoadFrom(dll);

                            // 查找实现了IPlugin接口的类型
                            var pluginTypes = pluginAssembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface);

                            foreach (var pluginType in pluginTypes)
                            {
                                IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
                                plugin.Initialize();
                                // 管理插件的代码
                                ListIPlugins.Add(plugin);
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine(e);

                            //throw;
                        }
                    }

                }));

            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
                //throw;
            }

        }
        /// <summary>
        /// 调用插件中的方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnShowPlugin_OnClick(object sender, RoutedEventArgs e)
        {
            Type plugin = ListIPlugins[0].GetType();

            MethodInfo showInfo = plugin.GetMethod("Show");//得到dll文件的中的方法

            showInfo.Invoke(ListIPlugins[0], null);//方法调用
        }


    }
}

4、以下内容是我开始做在线更新前查询的内容,希望能够帮助大家拓宽一下视野。

在C# WPF(Windows Presentation Foundation)应用程序中实现在线更新功能,可以通过以下几种方法和工具来实现:

  1. Squirrel: Squirrel是一个开源的安装和更新框架,专为.NET应用程序设计。它可以自动处理应用程序的安装、更新和卸载过程。Squirrel可以与WPF应用程序一起使用,以实现在线更新。https://github.com/Squirrelicon-default.png?t=N7T8https://github.com/Squirrel

  2. ClickOnce: ClickOnce是Microsoft提供的一种部署技术,允许开发者将应用程序发布到Web服务器或网络共享上。用户可以通过浏览器或Windows资源管理器安装和更新应用程序。ClickOnce适用于WPF应用程序,但可能需要一些配置和设置。(个人觉得操作比较繁琐,不喜欢)

  3. WyUpdate: WyUpdate是一个用于.NET应用程序的自动更新框架。它可以与WPF应用程序集成,实现在线更新。WyUpdate提供了一个服务器端组件,用于管理更新文件,以及一个客户端组件,用于在应用程序中检查和应用更新。(收费)

  4. AutoUpdater.NET: AutoUpdater.NET是一个简单易用的.NET库,用于实现WPF应用程序的自动更新。它允许开发者指定更新源(例如,Web服务器或FTP服务器),并在应用程序启动时检查更新。如果发现新版本,AutoUpdater.NET将自动下载并安装更新。AutoUpdater.NET: AutoUpdater 是c#.net下桌面应用程序自动更新的类库,使用非常简单,只需要一行代码就可以实现程序自动更新功能,支持.net4.5+,netcore3.1+,net5等,桌面程序支持winform和wpficon-default.png?t=N7T8https://gitee.com/stylexing/AutoUpdater.NET

 

在选择在线更新工具时,请考虑以下因素:

  • 应用程序的复杂性
  • 更新频率
  • 用户体验
  • 安全性
  • 跨平台支持(如果需要)

根据项目需求和团队技能选择合适的工具,以实现高效、安全的在线更新功能。

参考https://www.cnblogs.com/congroo/p/15655717.html

C#使用AutoUpdater.NET实现程序自动更新_C#教程_脚本之家

https://github.com/Squirrel

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为风而战

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值