Skip to main content
 首页 » 编程设计

winform软件版本检测自动升级开发流程(转)

2022年07月19日137mengfanrong

注:按此博文试验OK

2021/3/8 补充:

1、下载软件后进行试验,创建Export文件夹、创建program文件夹、创建DLL文件夹,几个项目分别编译到不同的文件夹中。

2、SoftUpdate.cs中的updateUrl 修改为服务器的ip,使用phpstudy2016进行服务器升级文件及xml文件的部署。

3、问题,升级进度条没有变化,待查。

基于C/S的开发有开发效率高,对于业务逻辑复杂,且不需要外网使用具有较大优势,但是弊端也不可忽视,就是升级麻烦,不可能每写一个版本就要拿着安装包给每个人去替换,这样不仅搞得自己很累,对于使用者来说也会厌烦,所以对于版本自动升级就显得必不可少,好,废话到此为止,下面直接上硬货

1、升级界面

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using Update;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;


namespace autoUpdate
{

public partial class Form1 : Form
{
[DllImport("zipfile.dll")]
public static extern int MyZip_ExtractFileAll(string zipfile, string pathname);
public Form1()
{
InitializeComponent();
//清除之前下载来的rar文件
if (File.Exists(Application.StartupPath + "\\Update_autoUpdate.zip"))
{
try
{
File.Delete(Application.StartupPath + "\\Update_autoUpdate.zip");
}
catch (Exception)
{


}

}
if (Directory.Exists(Application.StartupPath + "\\autoupload"))
{
try
{
Directory.Delete(Application.StartupPath + "\\autoupload", true);
}
catch (Exception)
{


}
}

//检查服务端是否有新版本程序
checkUpdate();
timer1.Enabled = true;
}
SoftUpdate app = new SoftUpdate(Application.ExecutablePath, "ExceTransforCsv");
public void checkUpdate()
{

app.UpdateFinish += new UpdateState(app_UpdateFinish);
try
{
if (app.IsUpdate)
{
app.Update();
}
else
{
MessageBox.Show("未检测到新版本!");
Application.Exit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

void app_UpdateFinish()
{
//解压下载后的文件
string path = app.FinalZipName;
if (File.Exists(path))
{
//后改的 先解压滤波zip植入ini然后再重新压缩
string dirEcgPath = Application.StartupPath + "\\" + "autoupload";
if (!Directory.Exists(dirEcgPath))
{
Directory.CreateDirectory(dirEcgPath);
}
//开始解压压缩包
MyZip_ExtractFileAll(path, dirEcgPath);

try
{
//复制新文件替换旧文件
DirectoryInfo TheFolder = new DirectoryInfo(dirEcgPath);
foreach (FileInfo NextFile in TheFolder.GetFiles())
{
File.Copy(NextFile.FullName, Application.StartupPath + "\\program\\" + NextFile.Name, true);
}
Directory.Delete(dirEcgPath, true);
File.Delete(path);
//覆盖完成 重新启动程序
path = Application.StartupPath + "\\program";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "ExceTransforCsv.exe";
process.StartInfo.WorkingDirectory = path;//要掉用得exe路径例如:"C:\windows";
process.StartInfo.CreateNoWindow = true;
process.Start();

Application.Exit();
}
catch (Exception)
{
MessageBox.Show("请关闭系统在执行更新操作!");
Application.Exit();
}
}
}

private void timer1_Tick(object sender, EventArgs e)
{
label2.Text = "下载文件进度:" + COMMON.CommonMethod.autostep.ToString() + "%";
this.progressBar1.Value = COMMON.CommonMethod.autostep;
if (COMMON.CommonMethod.autostep == 100)
{
timer1.Enabled = false;
}
}
}
}
有一点需要注意:zipfile.dll或者myzip.dll只能解压zip格式的压缩包 ,不要被带入误区,这个困扰我很久

2、版本检测升级类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Reflection;
using COMMON;
using System.Threading;

namespace Update
{
/// <summary>
/// 更新完成触发的事件
/// </summary>
public delegate void UpdateState();
/// <summary>
/// 程序更新
/// </summary>
public class SoftUpdate
{
private string download;
private const string updateUrl = "http://192.168.11.4:8055/update.xml";//升级配置的XML文件地址

#region 构造函数
public SoftUpdate() { }

/// <summary>
/// 程序更新
/// </summary>
/// <param name="file">要更新的文件</param>
public SoftUpdate(string file, string softName)
{
this.LoadFile = file;
this.SoftName = softName;
}
#endregion

#region 属性
private string loadFile;
private string newVerson;
private string softName;
private bool isUpdate;

/// <summary>
/// 或取是否需要更新
/// </summary>
public bool IsUpdate
{
get
{
checkUpdate();
return isUpdate;
}
}

/// <summary>
/// 要检查更新的文件
/// </summary>
public string LoadFile
{
get { return loadFile; }
set { loadFile = value; }
}

/// <summary>
/// 程序集新版本
/// </summary>
public string NewVerson
{
get { return newVerson; }
}

/// <summary>
/// 升级的名称
/// </summary>
public string SoftName
{
get { return softName; }
set { softName = value; }
}

private string _finalZipName = string.Empty;

public string FinalZipName
{
get { return _finalZipName; }
set { _finalZipName = value; }
}

#endregion

/// <summary>
/// 更新完成时触发的事件
/// </summary>
public event UpdateState UpdateFinish;
private void isFinish()
{
if (UpdateFinish != null)
UpdateFinish();
}

/// <summary>
/// 下载更新
/// </summary>
public void Update()
{
try
{
if (!isUpdate)
return;
WebClient wc = new WebClient();
string filename = "";
string exten = download.Substring(download.LastIndexOf("."));
if (loadFile.IndexOf(@"\") == -1)
filename = "Update_" + Path.GetFileNameWithoutExtension(loadFile) + exten;
else
filename = Path.GetDirectoryName(loadFile) + "\\Update_" + Path.GetFileNameWithoutExtension(loadFile) + exten;

FinalZipName = filename;
//wc.DownloadFile(download, filename);
wc.DownloadFileAsync(new Uri(download), filename);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
//wc.Dispose();

}
catch
{
throw new Exception("更新出现错误,网络连接失败!");
}
}

void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
(sender as WebClient).Dispose();
isFinish();
}

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{

//System.Diagnostics.Debug.WriteLine(e.ProgressPercentage);
COMMON.CommonMethod.autostep = e.ProgressPercentage;
//Thread.Sleep(100);

}

/// <summary>
/// 检查是否需要更新
/// </summary>
public void checkUpdate()
{
try
{
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(updateUrl);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(stream);
XmlNode list = xmlDoc.SelectSingleNode("Update");
foreach (XmlNode node in list)
{
if (node.Name == "Soft" && node.Attributes["Name"].Value.ToLower() == SoftName.ToLower())
{
foreach (XmlNode xml in node)
{
if (xml.Name == "Verson")
newVerson = xml.InnerText;
else
download = xml.InnerText;
}
}
}

Version ver = new Version(newVerson);
Version verson = Assembly.LoadFrom(loadFile).GetName().Version;
int tm = verson.CompareTo(ver);

if (tm >= 0)
isUpdate = false;
else
isUpdate = true;
}
catch (Exception ex)
{
throw new Exception("更新出现错误,请确认网络连接无误后重试!");
}
}

/// <summary>
/// 获取要更新的文件
/// </summary>
/// <returns></returns>
public override string ToString()
{
return this.loadFile;
}
}
}
3、主要复制进度条的value值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace COMMON
{
public static class CommonMethod
{
public static int autostep;
}
}
4、程序入口处检测版本是否更新

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Update;

namespace PrintDemo
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
if (checkUpdateLoad())
{
Application.Exit();
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static bool checkUpdateLoad()
{
bool result = false;
SoftUpdate app = new SoftUpdate(Application.ExecutablePath, "ExceTransforCsv");
try
{
if (app.IsUpdate && MessageBox.Show("检查到新版本,是否更新?", "版本检查", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
string path = Application.StartupPath.Replace("program", "");
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "autoUpdate.exe";
process.StartInfo.WorkingDirectory = path;//要掉用得exe路径例如:"C:\windows";
process.StartInfo.CreateNoWindow = true;
process.Start();

result = true;
}
else
{
result = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
result = false;
}
return result;
}
}
}
5、服务器上需要一个版本控制的xml,格式如下

<?xml version="1.0" encoding="utf-8" ?>
<Update>
<Soft Name="ExceTransforCsv">
<Verson>1.0.0.3</Verson>
<DownLoad>http://192.168.11.4:8055/Update_autoUpdate.zip</DownLoad>
</Soft>
</Update>
6、软件版本使用.net自带的版本控制即可,如下

7、重点强调,因为主程序升级需要将主程序关闭,所以需要将升级程序放到外边,将主程序放到program中,

运行界面:

首先感谢变成论坛上用户:wangnannan的帖子,通过他的代码我整理和优化的代码,以上为简单的代码复制,因为今天比较忙,来不及细致整理,等忙完这两天我会细化一下,我直接上附件,大家看源码一看就明白,

---------------------
原文:https://blog.csdn.net/xiaodong728/article/details/81083239


本文参考链接:https://www.cnblogs.com/xihong2014/p/10881693.html
阅读延展