设计自动升级软件

现在越来越多的软件具备了自动升级功能,用户在使用软件的过程中,软件自动通过网络从指定的服务器获得软件最新版本的信息,并自动下载相应的升级文件来实现软件版本的更新,免去了用户自己上网检查和下载软件的最新版本的麻烦,这是一项很贴心的功能,在一定程度上增加了软件的易用性和友好度。

  软件的自动升级功能可以独立于主程序,有一定的通用性,可作为一个单独的可执行程序由主程序调度运行。以下是我在Windows平台下设计自动升级软件中的一些收获和体会。

  自动升级软件是一个独立的应用程序(单独的可执行文件AutoUpdate.exe),供软件开发者编写代码,以外部程序的方式运行,例如调用ShellExecute这个API函数,或者在各种编程语言的中采用不同的方法来运行,C语言可以用system函数、Visual Basic语言则可以用Shell函数,其他语言也有类似的方法。

  自动升级软件的基本功能是对软件进行升级,首先需要能检测到软件最新版本的信息。软件开发者将软件最新版本的信息保存为一定格式的文件,放置到网络上固定的地址,自动升级软件访问该地址下载文件到本地,解析文件内容以进行升级。文件格式可以是任意的,但考虑到通用性,宜采用容易阅读、容易解析的文件格式。我采用的是INI初始化文件格式(此格式的文件内容以纯文本方式保存,内容被分为一个或多个区段,在区段下存放键、值对,通过区段名、键名可以取得对应的值,在Windows操作系统中可以通过GetPrivateProfile系列API函数读取到值)。下载文件时采用的通信协议也可以是任意的,但最好也是采用通用的成熟的协议,例如HTTP、FTP协议等,充分利用已有的技术,减少开发新协议的工作量。我采用的是HTTP协议,用WinInet系列API函数来实现文件的下载。自动升级软件每运行一次,便到指定的网址下载软件最新版本的信息文件,该网址以命令行参数传入,例如:AutoUpdate.exe /CheckURL=http://www.mysite.org/updatecofig.ini。在本地已经拥有升级配置文件的情况下,可省略此参数,此时自动升级软件将读取同目录下的updatecofig.ini文件的内容来获取软件最新版本的信息。

  下载到软件最新版本的信息文件(以下称之为配置文件)后,自动升级软件将解析该文件,根据文件内容来完成软件升级。配置文件必须满足一定的格式,我是通过读取[UPDATE]区段的AppName的值来判断该文件格式是否正确的,如果读到的是空内容则认为文件的格式不正确并停止升级。配置文件中包含软件最新的版本号(Version),用以和本地软件版本号相比较。本地软件版本号以命令行参数方式传入,例如:AutoUpdate.exe /CurrentVersion=1.1。在配置文件中,可以定义一系列的操作命令,包括下载、复制、移动、删除文件、运行外部程序等(最好是能够加上创建快捷方式、修改注册表、注册动态链接库文件等功能,因为时间关系这些功能尚未实现,可通过运行外部程序的方式达到同样的效果),最终完成软件的升级。一次升级需要更新的文件往往不止一个,配置文件中指定了要下载的文件总数(FileCount),以及各个文件的文件名(Name)、下载地址(URL)、文件大小(Size)和要更新到的路径(DestPath),为了确保下载到的文件内容的正确性,还给出了文件的校验码(Hash),在文件下载完毕时对文件进行校验,重新下载校验失败的文件。下载到的文件,有些是要更新到特殊目录(例如Windows系统目录)中去的,在指定DestPath时需要约定一些特殊目录的替换字符串(见附3),进行复制、移动、删除文件操作时将其替换成实际路径。

  在升级替换文件时,如果可执行文件或动态链接库等已驻留内存,由于操作系统的保护,文件替换是不能成功的,此时需要结束程序的运行再替换文件,也就是自动升级程序要通知正在运行的主程序:升级已经就绪、需要暂时结束程序来完成升级。通过在应用进程间发送消息的方法来实现升级完毕消息的传递,接收消息的目标窗口句柄、窗口标题、消息内容以命令行参数传入,例如:AutoUpdate.exe /NotifyWindow=12345 /NotifyWindowTitle=MyProgram /NotifyFinish=65535,/NotifyWindow和/NotifyWindowTitle两个参数只需要其中一个便可,升级完毕时将向目标窗口发送WM_USER类型的消息,WPARAM值为/NotifyFinish参数的值。

  自动升级软件的另一特点是升级行为是自动的,不需要或只需要很少的用户手动操作。升级可以在后台静默运行,执行完毕时提示用户软件已经升级完毕。在命令行参数中增加/Silence便可以静默方式运行自动升级程序。自动升级软件也可以以带进度显示的窗口方式运行,显示当前下载的文件、下载速度、完成比例和总升级进度等,让用户对升级过程有一个明确的了解。为了保持软件的友好性,软件开发者在调度自动升级程序时,也就是设计主程序时,应当允许用户对软件更新行为进行控制,可设置是否检测更新以及检测更新的时间周期。除非必须,应保留用户不对软件进行升级的选择权,升级只是一种建议,最好是能提示新版本软件优于以往版本的特性,让用户自己决定是否进行升级。

  为了满足多语言版本软件的需要,我在自动升级软件中设计了多语言功能,除了自动根据用户操作系统的语言在界面上显示不同的语言和提示信息(目前能在简体中文、繁体中文和英文版之间自动切换)外,软件升级需要更新的文件也可以因操作系统的语言而异。操作系统的语言代码可通过调用GetSystemDefaultLangID这个API函数获得。公共文件是不区分操作系统的语言的,而帮助文档等文件往往需要区分语言,简体中文的帮助文档不适用于繁体操作系统,反过来繁体中文的帮助文档亦不适用于简体操作系统。在升级配置文件中,可以在[LANGUAGE]区段指定在各种语言的操作系统下需要显示的提示信息和需要下载的文件。

  不同的软件,其自动升级程序应当可以分别独立地运行,互不干扰,但是同一软件的自动升级程序应当只能运行一个实例,否则可能会发生文件读写冲突等问题。启动自动升级软件时,以命令行参数方式传入要升级的软件名,例如AutoUpdate.exe /AppName=MyProgram /CurrentVersion=1.1,自动升级软件以此软件名创建互斥量,避免同时运行同一软件的多个自动升级程序实例。

附1:自动升级软件命令行参数释义
AutoUpdate.exe [/DEBUG] [/CheckURL=...] [/NotifyWindow=...] [/NotifyWindowTitle=...] [/NotifyFinish=...] [/Silence]
/DEBUG # 开启日志,升级过程中的信息将写入同目录下的debug.log文件中
/AppName= # 要升级的软件名,自动升级软件将以此名创建互斥量
/CurrentVersion= # 要升级的软件的当前版本
/CheckURL= # 下载升级配置文件的URL地址(要求必须是HTTP协议)
/NotifyWindow= # 升级完毕时接收通知消息的窗口句柄
/NotifyWindowTitle= # 升级完毕时接收通知消息的窗口标题
/NotifyFinish= # 升级完毕时发送的通知消息类型
/Silence # 以静默方式运行自动升级软件,不显示界面及任何提示
注意:以尖括号<>括起的参数为必要参数,以方括号[]括起的参数为可选参数。参数名和值之间以等号连接,不能插入多余的空格,如果参数值中间需要包含空格,应以引号括起整个值串;写代码调用AutoUpdate.exe程序时,如果文件路径包含空格,也应以引号括起全路径。

附2:更新配置文件updatecofig.ini的内容格式示例说明

[UPDATE] # 软件升级基本信息
AppName=MyProgram # 软件名,用以检验该更新配置文件的有效性
Version=1.2.3 # 软件的版本号
RunAfterDownload=Update.exe # 更新完毕后要执行的程序文件名

[COMMON] # 各语言版本公共文件
FileCount=2 # 要下载的文件数
File1=MyProgram.exe # 第一个文件名
File2=Update.exe # 第二个文件名
File3= # 第三个文件名

[LANGUAGE] # 支持的语言代码页对应的区段名
Default=ENG # 缺省语言——英语
0x0404=CHT # 繁体中文
0x0C04=CHT
1028=CHT
3076=CHT
0x0804=CHS # 简体中文
0x1004=CHS
2052=CHS
4100=CHS

[ENG]
Information=New version description... # 新版本软件优于以往版本的特性描述(英文)
FileCount=1 # 英文版专用文件数
File1=Help.chm # 第一个文件名
File2= # 第二个文件名

[CHT]
Information=硁ン穝弧 # 新版本软件优于以往版本的特性描述(繁体中文)
FileCount=1 # 繁体中文版专用文件数
File1=Help.chm # 第一个文件名
File2= # 第二个文件名

[CHS]
Information=软件更新说明…… # 新版本软件优于以往版本的特性描述(简体中文)
FileCount=1 # 简体中文版专用文件数
File1=Help.chm # 第一个文件名
File2= # 第二个文件名

[CommonFile1] # 第一个公共文件
Name=MyProgram.exe # 文件名
Size=3567811 # 文件大小
URL=http://www.mysite.org/download/1.2.3/MyProgram.exe # 文件下载地址
CompressMethod=None # 文件压缩方式
Hash=3177D58949143219E06E5C346674AE02 # 文件摘要码,用标准MD5算法得到
DestPath= # 文件安装路径,可包含路径变量,见附3

[CommonFile2] # 第二个公共文件
Name=Update.exe # 文件名
Size=172864 # 文件大小
URL=http://www.mysite.org/download/1.2.3/Update.exe # 文件下载地址
CompressMethod=None # 文件压缩方式
Hash=4914324AE021C3319E06E577D5894667 # 文件摘要码,用标准MD5算法得到
DestPath= # 文件安装路径,可包含路径变量,见附3

[ENGFile1] # 英文版第一个文件
Name=Help.chm # 文件名
Size=1581671 # 文件大小
URL=http://www.mysite.org/download/1.2.3/Help.ENG.chm # 文件下载地址
CompressMethod=None # 文件压缩方式
Hash=7D586493193219E0714E0274E5C3466A # 文件摘要码,用标准MD5算法得到
DestPath= # 文件安装路径,可包含路径变量,见附3

[CHTFile1] # 繁体中文版第一个文件
Name=Help.chm # 文件名
Size=1581369 # 文件大小
URL=http://www.mysite.org/download/1.2.3/Help.CHT.chm # 文件下载地址
CompressMethod=None # 文件压缩方式
Hash=66A3197D58649274E5C343219E0714E0 # 文件摘要码,用标准MD5算法得到
DestPath= # 文件安装路径,可包含路径变量,见附3

[CHSFile1] # 简体中文版第一个文件
Name=Help.chm # 文件名
Size=1581888 # 文件大小
URL=http://www.mysite.org/download/1.2.3/Help.CHS.chm # 文件下载地址
CompressMethod=None # 文件压缩方式
Hash=931932197D5864E0714E0C3466A274E5 # 文件摘要码,用标准MD5算法得到
DestPath= # 文件安装路径,可包含路径变量,见附3

附3:路径字符串变量中一些固定变量的替换

# 自动更新软件运行目录,即软件安装目录
# Windows程序文件目录,例如C:/Program Files
# Windows公共程序文件目录,例如C:/Program Files/Common Files
# 用户桌面目录
# Windows目录,例如C:/Windows
# Windows系统文件目录,例如C:/Windows/System32
# 临时文件目录,例如C:/Windows/Temp
# 开始菜单目录
# 开始菜单下的程序目录
# 开始菜单下的启动目录
# Windows任务条快速启动目录
# 我的文档目录
# 应用程序数据目录
# 用户目录,例如C:/Documents and Settings/Administrator

 

你可能感兴趣的:(设计自动升级软件)