winform+wcf搭建商户管理系统(4)- 在线自动更新功能的实现
- 功能展示
实现winform的在线更新,我这里主要实现了3部分的功能:
1.登录后检查更新

2.实现软件在运行中的实时更新提醒

3.在确认更新之后的在线更新功能


- 代码说明
1.实现登录时的检查更新
//检查版本更新
string version = Application.ProductVersion.ToString();
bool update = _client.TLoginCheckUpdate(version);
if (update)
{
DialogResult dialogResult = MessageBox.Show("系统存在更新,是否现在升级?", "升级提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (dialogResult == DialogResult.Yes)
{
System.Diagnostics.Process.Start(Path.Combine(Application.StartupPath, "Update.exe"), "true");
Application.Exit();
return;
}
}
在登录完成之后,获取本地主程序的的版本级别,远程与服务器最新版本的客户端版本号进行比较,从而获取版本是否需要更新。
在选择更新的时候,关闭主程序进程,运行更新程序。
2.主程序的实时更新检查
检查版本线程
private void FormMain_Load(object sender, EventArgs e)
{
try
{
label1.Visible = true;
backgroundWorker1.RunWorkerAsync();
tmTime.Start();
//开一个检测系统更新的线程
Thread thread = new Thread(new ParameterizedThreadStart(delegate
{
while (true)
{
//在线检查更新
bool result = _client.TLoginCheckUpdate(Application.ProductVersion.ToString());
if (result && OnCanBlinkChanged != null && _worned == false)
{
Action actionDelegate = () =>
{
OnCanBlinkChanged(this, new OparateEventArgs(true));
};
this.Invoke(actionDelegate);
_worned = true;
}
Thread.Sleep(10000);
}
}));
thread.IsBackground = true;
thread.Start();
}
catch (Exception ex)
{
warningBox1.ShowMessage(ex.Message, MessageType.Error, 3000, Color.Red);
}
}
获取到版本更新之后,提醒用户,然后闪烁Notify图标
private static void main_OnCanBlinkChanged(object sender, OparateEventArgs e)
{
if (e.CanOparate)
{
_recivedMessage = true;
_notify.ShowBalloonTip(3000, "更新提醒", "系统出现了新版本", ToolTipIcon.Info);
_timer.Start();
}
}
private static void timer_Tick(object sender, EventArgs e)
{
if (!_blink)
{
_notify.Icon = Resources.main;
}
else
{
_notify.Icon = Resources.blank;
}
_blink = !_blink;
}
3.在线更新的实现
远程获取需要新增、删除或者更新的文件列表
客户端代码
private void InitializeLstView()
{
string[] tempLst = null;
//获取当前的系统版本号
string rootUrl = Application.StartupPath;
List<string> conditions = new List<string>();
string[] files = Directory.GetFiles(rootUrl);
foreach (var item in files)
{
if (item.EndsWith("dll") || item.EndsWith("exe"))
{
FileVersionInfo version = FileVersionInfo.GetVersionInfo(item);
conditions.Add(Path.GetFileName(item) + ',' + version.FileVersion);
}
else
{
conditions.Add(Path.GetFileName(item) + ','); //listView1.Items.Add(new ListViewItem(new string[] { Path.GetFileName(item), "", "" }));
}
}
bool result = _client.TLoginUpdateSys(out tempLst, out _deleteLst, out _fileContent, conditions.ToArray());
if (result)
{
//添加删除列表
if (_deleteLst != null && _deleteLst.Length > 0)
{
lvUpdateList.Items.Add(new ListViewItem(new string[] { "文件删除个数:" + _deleteLst.Length, "", "0%" }));
}
//添加更新列表
List<string> lstFile = new List<string>();
foreach (string item in tempLst)
{
string[] arr = item.Split(';');
if (arr != null && arr.Length > 1)
{
string[] fileTemp = arr[0].Split('\\');
lvUpdateList.Items.Add(new ListViewItem(new string[] { fileTemp[fileTemp.Length - 1], arr[1], "0%" }));
lstFile.Add(arr[0]);
}
}
_fileLst = lstFile.ToArray();
}
else
{
lbState.Text = "获取更新文件失败!";
}
btnFinish.Enabled = !result;
btnNext.Enabled = result;
}
服务端代码
public bool Update(string[] currentFileVesion,out string[] uploadFileLst,out string[] deleteFileLst,out byte[][] fileContent)
{
bool result = true;
try
{
uploadFileLst = null;
fileContent = null;
deleteFileLst = null;
//记录原始版本,用于获取删除文件
Dictionary<string,string> sourceVesion = new Dictionary<string,string>();
if (currentFileVesion == null)
return false;
Array.ForEach(currentFileVesion, t =>
{
//fileName,Vesion
string[] ff = t.Split(',');
sourceVesion.Add(ff[0], ff[1]);
});
List<string> lstUpdate = new List<string>();
List<string> lstDelete = new List<string>();
//获取最新版本的更新目录
string rootUrl = Path.Combine(HttpRuntime.AppDomainAppPath,"Sys");
string[] versions = Directory.GetDirectories(rootUrl);
if (versions == null || versions.Length == 0)
return false;
Version lastestVersion = new Version("1.0");
string updateRoot = string.Empty;
Array.ForEach(versions, t =>
{
Version temp = new Version(Path.GetFileName(t));
if (temp > lastestVersion)
{
lastestVersion = temp;
updateRoot = t;
}
});
//获取更新内容
string[] updateFilePaths = Directory.GetFiles(updateRoot);
if (updateFilePaths == null || updateFilePaths.Length == 0)
return false;
Array.ForEach(updateFilePaths, t =>
{
string tempFileName=Path.GetFileName(t);
//判断目前版本是否存在该文件
bool exits = sourceVesion.ContainsKey(tempFileName);
//判断是否需要更新
if (exits)
{
if (tempFileName.EndsWith("dll") || tempFileName.EndsWith("exe"))
{
Version oldVesion = new Version(sourceVesion[tempFileName]);
FileVersionInfo versionTemp = FileVersionInfo.GetVersionInfo(t);
Version newVesion = new Version(versionTemp.FileVersion);
if (newVesion > oldVesion)
{
lstUpdate.Add(tempFileName);
}
}
sourceVesion.Remove(tempFileName);
}
else
{
lstUpdate.Add(tempFileName);
}
});
//获取需要删除的文件
foreach (var item in sourceVesion)
{
lstDelete.Add(item.Key);
}
deleteFileLst = lstDelete.ToArray();
//返回更新的内容
List<byte[]> lst = new List<byte[]>();
List<string> fileNames = new List<string>();
foreach (string item in lstUpdate)
{
string path = Path.Combine(updateRoot, item);
if (string.IsNullOrEmpty(item) || File.Exists(path) == false)
continue;
FileVersionInfo version = FileVersionInfo.GetVersionInfo(path);
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
lst.Add(buffer);
fileNames.Add(item + ";" + version.FileVersion);
}
}
uploadFileLst = fileNames.ToArray();
fileContent = lst.ToArray();
return result;
}
catch (Exception ex)
{
throw ex;
}
}
客户端后台更新类库
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//循环删除文件
for (int deleteIndex = 0; deleteIndex < _deleteLst.Length; deleteIndex++)
{
string deleteTemp = Path.Combine(Application.StartupPath, _deleteLst[deleteIndex]);
if (File.Exists(deleteTemp))
File.Delete(deleteTemp);
backgroundWorker1.ReportProgress(1, new int[] { deleteIndex, (deleteIndex + 1) * 100 / _deleteLst.Length });
}
//获取文件总大小
long totalSize = 0;
Array.ForEach(_fileContent, t => { totalSize += t.Length; });
long currentSize = 0;
//循环更新文件
for (int uploadIndex = 0; uploadIndex < _fileLst.Length; uploadIndex++)
{
string sourcePath = string.Empty;
string[] tempFile = _fileLst[uploadIndex].Split('\\');
//遍历文件夹,判断是否存在-不存在需要删除
for (int folderDeep = 0; folderDeep < tempFile.Length - 1; folderDeep++)
{
if (string.IsNullOrEmpty(sourcePath))
sourcePath = Path.Combine(Application.StartupPath, tempFile[folderDeep]);
else
sourcePath = Path.Combine(sourcePath, tempFile[folderDeep]);
if (Directory.Exists(sourcePath) == false)
Directory.CreateDirectory(sourcePath);
}
sourcePath = Path.Combine(Application.StartupPath, _fileLst[uploadIndex]);
if (File.Exists(sourcePath))
File.Delete(sourcePath);//删除要覆盖的文件
//开始写入新的文件
using (FileStream stream = new FileStream(sourcePath, FileMode.Append))
{
byte[] total = _fileContent[uploadIndex];
byte[] buffer = new byte[10240]; //10KB
long sCurrentSize = 0;
int piz = total.Length / buffer.Length;
for (int i = 0; i < piz; i++)
{
buffer = total.Skip(i * 10240).Take(buffer.Length).ToArray();
currentSize += buffer.Length;
sCurrentSize += buffer.Length;
stream.Write(buffer, 0, buffer.Length);
backgroundWorker1.ReportProgress((int)(currentSize * 100 / totalSize), new int[] { uploadIndex + _deleteLst.Length, (int)(sCurrentSize * 100 / total.Length) });
}
int left = total.Length % buffer.Length;
if (left > 0)
{
buffer = total.Skip(piz * 10240).Take(left).ToArray();
currentSize += buffer.Length;
stream.Write(buffer, 0, buffer.Length);
backgroundWorker1.ReportProgress((int)(currentSize * 100 / totalSize), new int[] { uploadIndex + _deleteLst.Length, 100 });
}
}
}
e.Result = null;
}
catch (Exception ex)
{
e.Result = ex.Message;
}
}
更新完成之后,将更新代码的程序关闭,开启客户端主线程
//关闭程序,开启主窗体
System.Diagnostics.Process.Start(Path.Combine(Application.StartupPath, "商户资料管理系统.exe"));
Application.Exit();

- 源码
客户端安装程序 网盘提取码(meat)

浙公网安备 33010602011771号