UpgraderDemo 项目分析¶
项目信息¶
- 项目名称: UpgraderDemo
- 下载链接: UpgraderDemo.rar
- 分析时间: 2026-03-31
项目概述¶
UpgraderDemo是一个演示软件自动更新功能的项目,包含两种版本控制模式:按日期(ByDateTime)和按数字版本号(ByNumber)。该项目展示了如何使用Upgrader组件实现HTTP方式的软件更新功能。
文件结构¶
UpgraderDemo/
├── ByDateTime/ # 按日期版本控制模式
│ ├── ByDateTime.py # 主程序文件
│ ├── ByDateTime.xml # 项目配置文件
│ ├── Extractor_Icon.ico # 应用程序图标
│ ├── Main.py # 主窗体代码
│ ├── Main.pydfm # 窗体设计文件
│ ├── Main.sct # 脚本文件
│ ├── Main.sfm # 窗体结构文件
│ └── update0.inf # 更新配置文件示例
└── ByNumber/ # 按数字版本控制模式
├── ByNumber.py # 主程序文件
├── ByNumber.xml # 项目配置文件
├── Extractor_Icon.ico # 应用程序图标
├── Main.py # 主窗体代码
├── Main.pydfm # 窗体设计文件
├── Main.sct # 脚本文件
├── Main.sfm # 窗体结构文件
└── update1.inf # 更新配置文件示例
主程序文件: ByDateTime.py / ByNumber.py¶
from glcl import *
from Main import *
def main():
Application.Initialize()
Application.Title = 'ByDateTime' # 或 'ByNumber'
Application.MainFormOnTaskbar = True
Application.Icon.LoadFromFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Extractor_Icon.ico"))
MainForm = frmMain(Application)
MainForm.Show()
FreeConsole()
Application.Run()
MainForm.Free()
if __name__ == '__main__':
main()
主窗体文件: Main.py¶
ByDateTime版本¶
# Powered By Python Studio, The best Python GUI IDE to download from glsite.com.
'''
功能:用于通过Http更新软件
特性:
1、阻塞模式更新
2、具备比较完备的进度控制
3、与autoupgrader组件相比,相对更简单些,但autoupgrader必须要求具备GUI,而这个组件则不需要。
4、具有自动回滚功能。如停止下载或下载失败都会执行回滚操作。
5、可将文件方便地下载到指定目录而不必须都下载到同一目录中。
组件属性:
UpdateInfoURL:更新信息文件的URL地址
VersionPattern:版本控制模式
vpByNumber:采用数字作为版本号,采用此模式,VersionAsNumber有效
vpByDateTime:采用日期作为版本号,采用此模式,VersionAsDateTime有效
组件事务:
OnProgress:进度控制
OnFileBegin:文件下载前
OnFileEnd:文件下载后
更新信息文件格式:
[version]
Pattern=1 //VersionPattern (0表示采用vpByDateTime, 1表示采用vpByNumber)
Version=2 //版本号,如果Pattern为0,则这里采用数字,否则使用日期字符串,如:2007-08-03 12:00:00
//下面是文件列表,格式为:本地路径=下载地址
//.表示当前目录,..表示上级目录,跟DOS下的表示是一样的。
[files]
../test/NBServer.exe=http://192.168.1.2:19130/nbmanager/NBServer.exe
./test/blacklist.sys=http://192.168.1.2:19130/nbmanager/blacklist.sys
test/client.exe=http://192.168.1.2:19130/nbmanager/bak/client.exe
config.ini=http://192.168.1.2:19130/nbmanager/config.ini
zend/1.exe=http://192.168.1.2:19130/nbmanager/test/1.exe
zend/2.exe=http://192.168.1.2:19130/nbmanager/test/2.exe
zend/3.exe=http://192.168.1.2:19130/nbmanager/test/3.exe
配置文件中的本地路径可以使用目录变量,如
%Windows%\setup.exe=http://192.168.1.2:19130/setup.exe
即表示将http://192.168.1.2:19130/setup.exe下载到本地的Windows目录下,并改名为setup.exe
可用的目录变量如下:
%Windows%
%System%
%Temp%
%Desktop%
%Programs%
%Personal%
%Startup%
%Recent%
%SendTo%
%StartMenu%
%DesktopDirectory%
%NetHood%
%Fonts%
%Templates%
%Common_StartMenu%
%Common_Programs%
%Common_Startup%
%Common_DesktopDirectory%
%AppData%
%PrintHood%
%Common_Favorites%
%Internet_Cache%
%Cookies%
%History%
使用相关说明,请参看update.inf和Demo(压缩包中的update.inf只是范本,只有放到Http服务器上才会生效)
注:新程序的版本号一定要大于旧程序的版本才会更新
'''
import os
from glcl import *
class frmMain(Form):
def __init__(self, owner):
self.ProgressBar1 = ProgressBar(self)
self.ProgressBar2 = ProgressBar(self)
self.Memo1 = Memo(self)
self.Label1 = Label(self)
self.btnStart = Button(self)
self.btnPause = Button(self)
self.btnResume = Button(self)
self.btnStop = Button(self)
self.Upgrader1 = Upgrader(self)
self.LoadProps(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Main.pydfm"))
self.Upgrader1.OnFileEnd = self.Upgrader1FileEnd
self.Upgrader1.OnProgress = self.Upgrader1Progress
self.Upgrader1.OnFileBegin = self.Upgrader1FileBegin
self.btnStop.OnClick = self.btnStopClick
self.btnResume.OnClick = self.btnResumeClick
self.btnPause.OnClick = self.btnPauseClick
self.btnStart.OnClick = self.btnStartClick
''' 这个实例演示的是使用日期更新的方式,为了保证演示效果长期有效,所以将版本
的日期设置为了一个比较远的,实际使用根据现实情况来。你当前做的更新版本的日期
设置控件和服务器端的inf文件中的日期,要比用户使用的版本的日期更新一些,这样
当用户端判断到了有更新日期的版本时,就可以进行更新了。如果你设置的日期是一个
比用户端版本还更早的日期,那是不会更新的。
'''
def btnStartClick(self, Sender):
if self.Upgrader1.Check(None): # 检查更新
self.Upgrader1.Start(None) # 开始更新
else: # 当前是最新版
self.Caption = '已经是最新的版本'
def btnPauseClick(self, Sender):
self.Upgrader1.Pause() # 暂停更新
def btnResumeClick(self, Sender):
self.Upgrader1.Resume() # 继续更新
def btnStopClick(self, Sender):
self.Upgrader1.Stop() # 停止更新
def Upgrader1FileBegin(self, url, localfile, Size): # 更新开始事件
self.Memo1.Lines.Add(url + '===>' + localfile)
def GetTimeString(self, Time) -> str: # 计算时间的函数
if Time >= 3600:
return '%d小时%2d分钟%2d秒钟'.format((Time // 3600), ((Time % 3600) // 60), (Time % 60))
else:
if Time >= 60:
return '%2d分钟%2d秒钟'.format((Tme // 60), (Time % 60))
else:
return str(Time) + '秒钟'
def Upgrader1Progress(self, ProgressEx, ulStatusCode, szStatusText): # 更新进度事件
if ProgressEx.Single.TotalSize != 0: # 一开始时未获取到单文件大小,需要排除这种情况
self.Label1.Caption = str(ProgressEx.Single.FinishedSize) # 下载完成的大小
self.ProgressBar1.Position = round((ProgressEx.Single.FinishedSize / ProgressEx.Single.TotalSize) * 100) # 计算单文件进度
if ProgressEx.General.TotalSize != 0: # 一开始时未获取到总文件大小,需要排除这种情
self.ProgressBar2.Position = round((ProgressEx.General.FinishedSize / ProgressEx.General.TotalSize) * 100) # 计算总文件进度
self.Label1.Caption = '文件个数:' + str(ProgressEx.FileCount) # 文件个数
def Upgrader1FileEnd(self, url, localfile, Size):
self.Memo1.Lines.Add('传输完成:' + localfile)
ByNumber版本¶
ByNumber版本的Main.py与ByDateTime版本基本相同,主要区别在于注释说明和版本控制模式。
更新配置文件示例¶
ByDateTime/update0.inf (按日期版本控制)¶
[Version]
Pattern=0
Version=2049/10/1 12:00:00
[files]
.\ByDateTime.exe=http://myupdate.top/COMPONENTS/Upgrader/ByDateTime.exe
.\1.mp4=http://myupdate.top/COMPONENTS/Upgrader/1.mp4
.\readme.txt=http://myupdate.top/COMPONENTS/Upgrader/readme.txt
ByNumber/update1.inf (按数字版本控制)¶
[Version]
Pattern=1
Version=2
[files]
.\ByNumber.exe=http://myupdate.top/COMPONENTS/Upgrader/ByNumber.exe
.\1.mp4=http://myupdate.top/COMPONENTS/Upgrader/1.mp4
.\readme.txt=http://myupdate.top/COMPONENTS/Upgrader/readme.txt
设计文件: Main.sct¶
def btnStartClick(Sender):
def btnPauseClick(Sender):
def btnResumeClick(Sender):
def btnStopClick(Sender):
def Upgrader1FileBegin(url, localfile, Size):
def Upgrader1Progress(ProgressEx, ulStatusCode, szStatusText):
def Upgrader1FileEnd(url, localfile, Size):
设计文件: Main.sfm (示例结构)¶
object frmMain: TForm
Left = 0
Top = 0
Caption = 'frmMain'
ClientHeight = 400
ClientWidth = 600
object ProgressBar1: TProgressBar
Left = 20
Top = 20
Width = 560
Height = 25
end
object ProgressBar2: TProgressBar
Left = 20
Top = 60
Width = 560
Height = 25
end
object Memo1: TMemo
Left = 20
Top = 100
Width = 560
Height = 200
end
object Label1: TLabel
Left = 20
Top = 320
Width = 200
Height = 20
Caption = '文件个数:0'
end
object btnStart: TButton
Left = 20
Top = 350
Width = 75
Height = 25
Caption = '开始'
OnClick = btnStartClick
end
object btnPause: TButton
Left = 110
Top = 350
Width = 75
Height = 25
Caption = '暂停'
OnClick = btnPauseClick
end
object btnResume: TButton
Left = 200
Top = 350
Width = 75
Height = 25
Caption = '继续'
OnClick = btnResumeClick
end
object btnStop: TButton
Left = 290
Top = 350
Width = 75
Height = 25
Caption = '停止'
OnClick = btnStopClick
end
object Upgrader1: TUpgrader
Left = 380
Top = 350
OnFileBegin = Upgrader1FileBegin
OnProgress = Upgrader1Progress
OnFileEnd = Upgrader1FileEnd
end
end
其他文件¶
- Extractor_Icon.ico: 应用程序图标文件
- ByDateTime.xml / ByNumber.xml: 项目配置文件
- Main.pydfm: 窗体设计文件(二进制格式)
详细分析¶
功能概述¶
UpgraderDemo展示了两种软件自动更新方案:
- 按日期版本控制 (ByDateTime)
- 使用日期作为版本标识
- 适用于需要按时间顺序更新的场景
-
示例版本:2049/10/1 12:00:00
-
按数字版本控制 (ByNumber)
- 使用数字作为版本标识
- 适用于传统的版本号管理
- 示例版本:2
核心功能特性¶
- 阻塞模式更新: 更新过程中会阻塞用户界面,确保更新完整性
- 进度控制: 提供详细的下载进度显示,包括单个文件和总体进度
- 自动回滚: 下载失败或中断时自动回滚到更新前状态
- 灵活的文件下载: 支持将文件下载到任意指定目录
- 目录变量支持: 支持系统目录变量(如%Windows%、%Temp%等)
- 版本检查: 自动检查新版本,只有新版本才会触发更新
使用的组件¶
- 主窗体组件:
-
frmMain(TForm): 主窗体容器 -
界面控件:
ProgressBar1,ProgressBar2(TProgressBar): 进度条,显示下载进度Memo1(TMemo): 文本显示区域,显示下载日志Label1(TLabel): 标签,显示文件数量等信息-
btnStart,btnPause,btnResume,btnStop(TButton): 控制按钮 -
核心功能组件:
Upgrader1(TUpgrader): 更新器组件,负责HTTP下载和版本管理
技术特点¶
1. 版本控制模式¶
- vpByDateTime: 日期模式,使用日期字符串作为版本号
- vpByNumber: 数字模式,使用整数作为版本号
2. 事件处理机制¶
OnFileBegin: 文件开始下载时触发OnProgress: 下载进度更新时触发OnFileEnd: 文件下载完成时触发
3. 进度信息结构¶
ProgressEx.Single: 单个文件的进度信息ProgressEx.General: 总体进度信息ProgressEx.FileCount: 文件总数
4. 更新配置文件格式¶
[Version]部分: 定义版本控制模式和版本号[files]部分: 定义文件下载映射关系
窗体属性¶
- caption: frmMain
- height: 400
- width: 600
代码分析¶
导入的模块:
- import os: 操作系统接口模块
- from glcl import *: GUI组件库
定义的类:
- frmMain: 主窗体类,继承自Form
定义的方法:
- __init__: 构造函数,初始化窗体和控件
- btnStartClick: 开始更新按钮点击事件
- btnPauseClick: 暂停更新按钮点击事件
- btnResumeClick: 继续更新按钮点击事件
- btnStopClick: 停止更新按钮点击事件
- Upgrader1FileBegin: 文件开始下载事件
- Upgrader1Progress: 下载进度更新事件
- Upgrader1FileEnd: 文件下载完成事件
- GetTimeString: 辅助函数,格式化时间显示
事件绑定:
- self.btnStart.OnClick = self.btnStartClick
- self.btnPause.OnClick = self.btnPauseClick
- self.btnResume.OnClick = self.btnResumeClick
- self.btnStop.OnClick = self.btnStopClick
- self.Upgrader1.OnFileBegin = self.Upgrader1FileBegin
- self.Upgrader1.OnProgress = self.Upgrader1Progress
- self.Upgrader1.OnFileEnd = self.Upgrader1FileEnd
使用说明¶
1. 配置更新服务器¶
- 将
update.inf文件上传到HTTP服务器 - 在
update.inf中配置正确的版本信息和文件列表 - 确保所有需要下载的文件可以通过指定的URL访问
2. 客户端配置¶
- 设置
Upgrader1.UpdateInfoURL属性为更新配置文件的URL - 根据需求设置
VersionPattern属性(vpByDateTime或vpByNumber) - 设置相应的版本号属性(