更新--本地检查需要下载/删除的文件,然后做替换/删除,并重启
如何制作自动更新程序?
[版权所有 邱秋 2014 metaphysis@yeah.net, 转载请注明出处]
最近为单位写了一个C/S结构的软件,这个软件是工作在单位的局域网内的。为了减轻为程序进行升级的工作量,需要解决程序自动更新的问题。那么如何做一个自动更新程序呢?
想了一下,更新程序需要解决以下问题:
(A)它需要知道哪些是需要更新的文件,哪些是不需要的文件;
(B)它需要知道从哪里下载更新文件;
(C) 它需要将更新的文件下载下来,并将旧的文件替换掉,将不再需要的文件删除掉;
(D)它需要能够在更新完毕后自动重新启动程序以便用户继续使用;
问题(A)可以通过版本控制的方法来解决。具体方法是为程序所使用的文件都设定一个版本号,所有文件的版本号都记录在一个 XML 文件中,当升级时,检查最新程序的版本控制文件和当前的版本控制文件,当版本号较大时,则表示该文件需要更新。最新的版本控制文件可以放在一个匿名 FTP 上以便程序下载下来和本地的版本控制文件进行比对。如果一个文件不再需要了,则将该文件的版本信息从最新的版本控制文件中删除,通过对比控制文件,就知道该文件不再需要了,可以将之删除。由于我写的程序除主程序外,其他组件都不会发生太多改动,所以我使用了如下的方式来表示一个文件的版本信息:
- <?xml version="1.0" encoding="utf-8"?>
- <AutoUpdater>
- <Updater>
- <UpdateUrl>ftp://192.168.1.24/update/</UpdateUrl>
- <MainVersion>1.1.102.0</MainVersion>
- <LastUpdateTime>2014-01-27</LastUpdateTime>
- <UpdateDescription>自动更新程序</UpdateDescription>
- </Updater>
- <UpdateFileList>
- <UpdateFile Version="2.2.5.0" Name="AForge.dll" />
- <UpdateFile Version="2.2.5.0" Name="AForge.Video.DirectShow.dll" />
- <UpdateFile Version="2.2.5.0" Name="AForge.Video.dll" />
- <UpdateFile Version="1.0.100.0" Name="USBCleaner.exe" />
- <UpdateFile Version="1.0.100.0" Name="USBViewer.exe" />
- </UpdateFileList>
- </AutoUpdater>
UpdateUrl 告诉程序要从什么地方下载最新的版本控制文件和更新文件,这里我使用了 FTP 的方式,这样简单一些,我将版本控制文件和最新的程序文件都放在了 ftp://192.168.1.24/update/ 下。MainVersion 表示程序的版本,用来确定是否需要进行升级。LastUpdateTime 表示程序最后的更新时间。UpdateDescription 表示更新程序的描述。UpdateFile 则表示程序中的每一个文件条目,Version 表示其版本,Name 表示相对于程序根目录的文件路径名,如果文件是在根目录下面,则直接是文件名,如果是在子目录下,则在前面加上相应的子目录。
有了这个版本控制文件,问题(B)也解决了,因为从指定的地址下载即可。
问题(C)可以通过比对版本控制文件,确定需要下载的文件和不再需要的文件。然后通过 WebClient 类来下载需要的文件。
问题(D)可以这样解决,主程序先检查是否有升级,如果有升级,则将旧的更新程序再复制一份,启动复制的更新程序,并启动它来下载更新文件,这样的话,就可以解决更新更新程序本身的问题,因为将新的更新程序下载来后,可以直接覆盖掉原始的更新程序而不会产生文件正在使用无法更新的问题,因为运行的是旧的更新程序的副本,在全部更新完毕后,主程序中可以加一段代码检测是否有更新副本产生,只要有就将它删除即可。
想清楚了这些问题,就是具体代码实现了,以下把版本文件解析的代码和更新下载文件的代码贴出来,整个更新模块也提供了下载,供有兴趣的朋友参考使用。下载链接:http://download.csdn.net/detail/metaphysis/6891593。
- XmlVersionConfigFile.vb
- Imports System.Xml
- Imports System.Xml.Linq
- Public Class XmlVersionConfigFile
- Public Property UpdateUrl As String = String.Empty
- Public Property MainVersion As Version = Version.Parse("0.0.0.0")
- Public Property LastUpdateTime As Date = DateTimePicker.MinimumDateTime
- Public Property UpdateDescription As String = String.Empty
- Public Property UpdateFileList As Dictionary(Of String, Version) = Nothing
- Public Sub New(ByVal fileContent As String)
- ParseXmlVersionFile(fileContent)
- End Sub
- Private Function ParseXmlVersionFile(ByVal fileContent As String) As Boolean
- Dim xdoc As XDocument = Nothing
- Try
- xdoc = XDocument.Parse(fileContent)
- Catch ex As Exception
- Return False
- End Try
- Me.UpdateUrl = xdoc.Element("AutoUpdater").Element("Updater").Element("UpdateUrl").Value
- Me.MainVersion = Version.Parse(xdoc.Element("AutoUpdater").Element("Updater").Element("MainVersion").Value)
- Date.TryParse(xdoc.Element("AutoUpdater").Element("Updater").Element("LastUpdateTime").Value, Me.LastUpdateTime)
- Me.UpdateDescription = xdoc.Element("AutoUpdater").Element("Updater").Element("UpdateDescription").Value
- Me.UpdateFileList = New Dictionary(Of String, Version)
- Dim query = From UpdateFile In xdoc.Descendants("UpdateFile") Select UpdateFile
- For Each fileInfo As XElement In query
- Me.UpdateFileList.Add(fileInfo.Attribute("Name").Value.ToLower, Version.Parse(fileInfo.Attribute("Version").Value))
- Next
- Return True
- End Function
- End Class
- UpdatingForm.vb
- Imports System.IO
- Public Class UpdatingForm
- Public Property LocalVersionConfig As XmlVersionConfigFile = Nothing
- Public Property ServerVersionConfig As XmlVersionConfigFile = Nothing
- Private WithEvents webClient As New System.Net.WebClient
- Private _downloadIndex As Integer
- Private _localConfigFileName As String = "version.xml"
- Private _localXmlFilePath As String = Path.Combine(Application.StartupPath, _localConfigFileName)
- Private _updateUrl As String = String.Empty
- Private _deleteFileList As New List(Of String)
- Private Sub webClient_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) Handles webClient.DownloadFileCompleted
- Me.lvwFile.Items(_downloadIndex).ImageIndex = 2
- lblSinglePercent.Text = "0%"
- prbSingle.Value = 0
- DownloadNextFile()
- End Sub
- Private Sub webClient_DownloadProgressChanged(ByVal sender As System.Object, ByVal e As System.Net.DownloadProgressChangedEventArgs) Handles webClient.DownloadProgressChanged
- Dim currentPercent As String = e.ProgressPercentage & "%"
- If currentPercent <> Me.lvwFile.Items(_downloadIndex).SubItems(3).Text Then
- Me.lvwFile.Items(_downloadIndex).SubItems(3).Text = currentPercent
- prbSingle.Value = e.ProgressPercentage
- lblSinglePercent.Text = currentPercent
- prbAll.Value = Int((_downloadIndex + 1) / Me.lvwFile.Items.Count * 100)
- lblAllPercent.Text = prbAll.Value & "%"
- End If
- End Sub
- Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQuit.Click
- Me.Close()
- End Sub
- Private Sub DownloadNextFile()
- If _downloadIndex < (lvwFile.Items.Count - 1) Then
- _downloadIndex += 1
- lvwFile.Items(_downloadIndex).ImageIndex = 1
- Try
- Dim destPath As String = IO.Path.Combine(Application.StartupPath, lvwFile.Items(_downloadIndex).SubItems(1).Text)
- File.Delete(destPath)
- webClient.DownloadFileAsync(New Uri(_updateUrl & lvwFile.Items(_downloadIndex).SubItems(1).Text), destPath)
- Catch ex As Exception
- Me.lvwFile.Items(_downloadIndex).ImageIndex = 3
- MsgBox("下载文件发生错误,更新失败。错误原因: " & ex.Message, MsgBoxStyle.Critical, "错误")
- Me.Close()
- End Try
- Else
- UpdateFileCompleted()
- End If
- End Sub
- Private Sub UpdateFileCompleted()
- ' 更新显示信息。
- prbSingle.Value = prbSingle.Maximum
- lblSinglePercent.Text = "100%"
- lblAllPercent.Text = "100%"
- ' 删除不需要的文件。
- For Each f As String In _deleteFileList
- Try
- File.Delete(Path.Combine(Application.StartupPath, f))
- Catch ex As Exception
- '
- End Try
- Next
- Me.btnQuit.Enabled = True
- Process.Start(IO.Path.Combine(Application.StartupPath, "szpt.exe"))
- Me.Close()
- End Sub
- Private Sub LoadUpdateFile()
- _updateUrl = Me.ServerVersionConfig.UpdateUrl
- ' 查找客户端需要更新的文件和需要删除的文件。
- For Each p As KeyValuePair(Of String, Version) In Me.LocalVersionConfig.UpdateFileList
- If Me.ServerVersionConfig.UpdateFileList.ContainsKey(p.Key) Then
- If Me.ServerVersionConfig.UpdateFileList(p.Key) > Me.LocalVersionConfig.UpdateFileList(p.Key) Then
- Dim item As ListViewItem = Me.lvwFile.Items.Add(String.Empty, 0)
- item.SubItems.Add(p.Key)
- item.SubItems.Add(Me.ServerVersionConfig.UpdateFileList(p.Key).ToString)
- item.SubItems.Add(String.Empty)
- End If
- Else
- _deleteFileList.Add(p.Key)
- End If
- Next
- ' 查找服务器端新增需要下载的文件。
- For Each p As KeyValuePair(Of String, Version) In Me.ServerVersionConfig.UpdateFileList
- If Me.LocalVersionConfig.UpdateFileList.ContainsKey(p.Key) = False Then
- Dim item As ListViewItem = Me.lvwFile.Items.Add(String.Empty, 0)
- item.SubItems.Add(p.Key)
- item.SubItems.Add(p.Value.ToString)
- item.SubItems.Add(String.Empty)
- End If
- Next
- ' 版本控制文件为必须下载文件。
- Dim itemVersion As ListViewItem = Me.lvwFile.Items.Add(String.Empty, 0)
- itemVersion.SubItems.Add("version.xml")
- itemVersion.SubItems.Add(Me.ServerVersionConfig.MainVersion.ToString)
- itemVersion.SubItems.Add(String.Empty)
- ' 设置当前下载的文件序数。
- _downloadIndex = -1
- End Sub
- Private Sub UpdatingForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
- LoadUpdateFile()
- DownloadNextFile()
- End Sub
- End Class
更新--本地检查需要下载/删除的文件,然后做替换/删除,并重启相关推荐
- 删除顽固文件的执行代码,删除rhsa属性文件,删除服务器中黑客留下...
删除顽固文件的执行代码,删除rhsa属性文件,删除服务器中黑客留下的畸形文件文件有时候服务器的网站空间被黑客入侵,上传了删除不了的文件,我们可以用bat代码来执行删除. DEL /F /A /Q ...
- 360android文件恢复,删除的文件怎么恢复?360删除的文件怎么恢复?
如今几乎所有人都会使用一款安全软件,电脑垃圾的清理电脑防毒等都必须用到一款安全软件,但是这些安全软件有时在清理垃圾删除一些文件的时候可能会删除一些不该删除的文件,那么删除的文件怎么恢复?360删除的文 ...
- java 删除过期文件_定时脚本: 删除HDFS中的过期文件
1. 基本原理: 通过hadoop fs -ls *命令获取相关文件或目录的修改时间,然后与设定的过期时间进行比较,之后执行删除操作即可 2. 相关代码: #!/bin/bash source ~/. ...
- 服务器删除的文件不在回收站,删除的文件不在回收站能恢复吗?
删除的文件不在回收站能恢复吗?当然可以,大家都知道,回收站是操作系统里的其中一个系统文件夹,主要用来存放用户临时删除的文档资料,存放在回收站的文件可以恢复.它的设置是帮助我们更加方便的维护文档的.有些 ...
- linux删除垃圾文件夹,优雅地删除 Linux 中的垃圾文件第六季
当然,我们也可以使用 find 命令查找并删除超过 x 天未访问的文件,不过 tmpwatch 可以一步到位,何乐而不为? tmpwatch 默认根据文件或目录的访问时间(access time)来决 ...
- python删除某个文件夹_Python 实现删除某路径下文件及文件夹
Python 实现删除某路径下文件及文件夹的脚本 #!/usr/bin/env python import os import shutil delList = [] delDir = "/ ...
- 手机里android文件里哪些文件可删除,手机文件夹哪些可以删除?这4个删除它妥妥的...
原标题:手机文件夹哪些可以删除?这4个删除它妥妥的 我们手机在使用一段时间后都会产生一定的数据缓存,新手机可能没有感觉,但是就手机就会体现得非常明显.因为随着手机里的使用数据越来越多,你会发现手机慢慢 ...
- sql服务器怎么删除日志文件,SQL数据库怎么删除日志ldf
一.简单方法 –SQL Server收缩方法 1.右键数据库→属性→选项→故障还原模型→设为简单→确定: 2.右键数据库→所有任务→收缩数据库→确定: 3.右键数据库→属性→选项→故障还原模型→设为大 ...
- linux 下删除批量文件命令,linux 批量删除文件与空文件删除命令linux操作系统 -电脑资料...
在linux中删除文件与删除目录及删除空文章都是使用rm 命令了,执行rm指令可删除文件或目录,如欲删除目录必须加上参数\"-r\",否则预设仅会删除文件,下面我来介绍在linux ...
最新文章
- mysql数据库实验报告jdbc_Jdbc连接数据库实验报告(2)
- jQuery-切换2
- StaggeredGridView 实现分析--首次填充过程(一)
- c语言 char转int_图文并茂,一文讲透C语言结构体内存对齐
- python字符串排序_Python对字符串列表进行排序
- 一个菜鸟怎样做好功能测试?
- springboot 分页查询参数_精通SpringBoot--分页查询功能的实现
- 【shell系列】之正则表达式
- leetcode[232]用栈实现队列/Implement Queue using Stacks
- 豪华版飞机大战系列(三)
- 【Android工具】更新Yandex有道云笔记网页剪辑插件测试正常!可以安装PCchrome插件的手机浏览器!...
- Instagram的百万美元Bug
- 汇编达人视频学习4(MOVS、STOS、REP、PUSH、POP、JMP、CALL、RET指令)
- 小程序中实现用户的登录与注册
- 电商后台管理系统(一)项目搭建
- 虚幻4连接mysql蓝图教程_ue4商城资源MySQL Integration数据库集成插件
- APP - IOS_Application 常用推荐
- openlayers结合谷歌api进行地图定位
- 远景论坛找不到服务器,远景论坛 PCBeta 无法访问的临时解决办法
- 磁共振t1t2信号记忆顺口溜_医学影像分割入门、MRI、t1、t2等序列概念