Delphi 实现软件自动升级的功能
发布时间 - 2026-01-11 03:05:37 点击率:次Delphi 实现软件自动升级的功能

原理简单,在FTP上维护一个Update.ini文件,里面记录着要更新文件的版本号,本地也有一个Update.ini文件,每次启动更新程序时,先从FTP上下载Update.ini文件到本地名字为Update_new.ini,然后比较这两个文件,如果新的版本号大于旧的,或者新的文件在就ini中没有,这些就表示要更新的文件,然后逐一下载。
本程序名字为AutoUpdate,你生成这个exe,然后和主程序一起打包,创建桌面快捷方式时,指向AutoUpdate,而不是主程序。
在本地还有一个ini文件,比如叫ftp.ini吧,里面内容是
[coninfo]
main=Project1.exe
param={app}sayyes.pj2 -y bde.txt
main=Project1.exe:是主程序名称,和升级程序在同一目录
param={app}sayyes.pj2 -y bde.txt:这是命令行参数,app为当前路径,在程序中替换掉,传递给主程序(如果需要的话)
update.ini的内容格式如下
[root]
办事处查询.txt=20100519
[dbcard]
sayyes.pj2=20100519
FTP用户密码.txt=20100519
[root]代表根目录,后面的[dbcard]代表子目录,依次类推
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdHTTP, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdFTP, ComCtrls, ExtCtrls,IniFiles,ShellAPI, jpeg;
type
TfrmMain = class(TForm)
IdFTP1: TIdFTP;
IdHTTP1: TIdHTTP;
ProgressBar1: TProgressBar;
GroupBox1: TGroupBox;
ld_host: TLabeledEdit;
ld_username: TLabeledEdit;
ld_psw: TLabeledEdit;
ld_port: TLabeledEdit;
Label1: TLabel;
cb_mode: TComboBox;
ProgressBar2: TProgressBar;
Label3: TLabel;
list_file: TListView;
Label4: TLabel;
procedure IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);
procedure IdFTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
procedure FormCreate(Sender: TObject); private
{ Private declarations }
FSize:Integer;
FPath: string;
FExePath: string;
FInitPath: string;
FIniFile:TIniFile;
FHandle:HWND;
FMainExe:string;
FParam: string;
procedure CheckUpdateList;
function ConnectFTP:Boolean;
procedure DownLoadFile;
procedure LoadIni;
procedure SaveIni;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
uses
Flash;
{$R *.dfm}
//下载进度
procedure TfrmMain.IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);
begin
ProgressBar1.Position := AWorkCount;
Application.ProcessMessages;
end;
procedure TfrmMain.IdFTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
begin
ProgressBar1.Position := 0;
ProgressBar2.StepBy(1);
end;
procedure TfrmMain.FormCreate(Sender: TObject);
var
frm: TfrmFlash;
begin
Self.Visible := False;
//闪屏,可以不加
frm := TfrmFlash.Create(nil);
frm.Show;
Application.ProcessMessages;
FExePath := ExtractFilePath(Application.ExeName);
FIniFile := TIniFile.Create(FExePath+'ftp.ini');
//加载ini信息,就是主机和端口之类的信息
LoadIni;
try
ConnectFTP;
CheckUpdateList;
Self.Visible := True;
Application.ProcessMessages;
DownLoadFile;
finally
FreeAndNil(frm);
IdFTP1.Quit;
FParam := StringReplace(FParam,'{app}',FExePath,[rfReplaceAll]);
//更新完毕后,启动主程序,并传入命令行参数
ShellExecute(Handle,'open',PChar(FExePath+FMainExe),PChar(FParam),nil,SW_NORMAL);
Application.Terminate;
end;
end;
//检查更新列表
procedure TfrmMain.CheckUpdateList;
var
oldFile,newFile:TStringList;
i,ver,index:Integer;
itemstr,itempath: string;
item:TListItem;
begin
oldFile := TStringList.Create;
newFile := TStringList.Create;
try
list_file.Clear;
//先下载服务器上的update.ini文件,存到本地update_new.ini
IdFTP1.Get('update.ini',FExePath+'update_new.ini',True);
if FileExists(FExePath + 'update.ini') = False then Exit;
oldFile.LoadFromFile(FExePath + 'update.ini');
newFile.LoadFromFile(FExePath + 'update_new.ini');
itempath := '';
//下面开始比较两个list,如果newFile的版本号大于oldFile的版本号或者oldFile中没有的都表示要更新的
for i := 0 to newFile.Count - 1 do
begin
itemstr := newFile.Strings[i];
if itemstr = '' then Continue;
if itemstr[1] = '[' then
begin
itempath := Copy(itemstr,2,Length(itemstr)-2);
//如果是根目录
if itempath = 'root' then
itempath := '/';
Continue;
end;
itemstr := newFile.Names[i];
index := oldFile.IndexOfName(itemstr);
if index = - 1 then
begin
item := list_file.Items.Add;
item.Caption := itemstr;
item.SubItems.Add(itempath)
end
else
begin
ver := StrToIntDef(newFile.Values[itemstr],0);
if ver > StrToIntDef(oldFile.Values[itemstr],0) then
begin
item := list_file.Items.Add;
item.Caption := itemstr;
item.SubItems.Add(itempath);
end;
end;
end;
if list_file.Items.Count = 0 then Application.Terminate;
finally
oldFile.Free;
newFile.Free;
end;
end;
function TfrmMain.ConnectFTP: Boolean;
begin
Result := False;
try
IdFTP1.Host := ld_host.Text;
IdFTP1.Port := StrToIntDef(ld_port.Text,21);
IdFTP1.Username := ld_username.Text;
IdFTP1.Password := ld_psw.Text;
IdFTP1.Connect;
IdFTP1.Passive := cb_mode.ItemIndex = 1;
FInitPath := IdFTP1.RetrieveCurrentDir;
Result := IdFTP1.Connected;
except
Result := False;
end;
end;
//下载文件更新
procedure TfrmMain.DownLoadFile;
var
i:Integer;
path:string;
s1,s2:String;
begin
ProgressBar2.Max := list_file.Items.Count;
ProgressBar2.Position := 0;
FIniFile.EraseSection('error');
for i := 0 to list_file.Items.Count - 1 do
begin
Label4.Caption := '正在下载 '+list_file.Items[i].Caption;
Application.ProcessMessages;
IdFTP1.ChangeDir(FInitPath);
path := list_file.Items[i].SubItems.Strings[0];
if path <>'/' then
begin
IdFTP1.ChangeDir(path);
ForceDirectories(FExePath+path);
s1 := list_file.Items[i].Caption;
s2 := FExePath+path+'/'+list_file.Items[i].Caption;
IdFTP1.Get(s1,s2,True);
end
else
begin
s1 := list_file.Items[i].Caption;
s2 := FExePath+'/'+list_file.Items[i].Caption;
IdFTP1.Get(s1,s2,True);
//记录失败项
FIniFile.WriteString('error',list_file.Items[i].Caption,'成功');
end;
except
//记录失败项
FIniFile.WriteString('error',list_file.Items[i].Caption,'失败');
end;
end;
Label4.Caption := '所有文件更新完毕!';
DeleteFile(FExePath+'update.ini');
CopyFile(PChar(FExePath+'update_new.ini'),PChar(FExePath+'update.ini'),False);
end;
procedure TfrmMain.LoadIni;
begin
ld_host.Text := FIniFile.ReadString('coninfo','host','******');
ld_username.Text := FIniFile.ReadString('coninfo','user','******');
ld_psw.Text := FIniFile.ReadString('coninfo','psw','******');
ld_port.Text := FIniFile.ReadString('coninfo','port','21');
cb_mode.ItemIndex := FIniFile.ReadInteger('coninfo','mode',1);
FMainExe := FIniFile.ReadString('coninfo','main','Main.exe');
FParam := FIniFile.ReadString('coninfo','param','');
end;
procedure TfrmMain.SaveIni;
begin
FIniFile.WriteString('coninfo','host',ld_host.Text);
FIniFile.WriteString('coninfo','user',ld_username.Text);
FIniFile.WriteString('coninfo','psw',ld_psw.Text);
FIniFile.WriteString('coninfo','port',ld_port.Text);
FIniFile.WriteInteger('coninfo','mode',cb_mode.ItemIndex);
end;
end.
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Delphi
# 实现软件自动升级的功能
# 软件的升级功能
# Delphi 用DLL实现插件的简单实例
# Delphi 根据字符串找到函数并执行的实例
# Delphi 中内存映射对于大文件的使用
# Delphi提取PDF文本实例
# Delphi XE5 为Android应用制作签名的方法(图文)
# ListView 百分比进度条(delphi版)
# Delphi实现截屏存盘的方法
# Delphi实现窗体感知鼠标滑过并自动隐藏与显示窗口的方法
# 主程序
# 命令行
# 这是
# 也有
# 如有
# 这两个
# 希望能
# 还有一个
# 谢谢大家
# 不加
# 快捷方式
# 而不是
# 升级程序
# 自动升级
# 疑问请
# 器上
# 加载
# 完毕后
# 在同一
# string
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
iOS UIView常见属性方法小结
如何在 React 中条件性地遍历数组并渲染元素
laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
PHP 500报错的快速解决方法
EditPlus 正则表达式 实战(3)
简单实现jsp分页
Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例
如何构建满足综合性能需求的优质建站方案?
lovemo网页版地址 lovemo官网手机登录
怎样使用JSON进行数据交换_它有什么限制
如何快速建站并高效导出源代码?
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
如何快速搭建高效服务器建站系统?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
如何在宝塔面板中修改默认建站目录?
如何正确选择百度移动适配建站域名?
Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门
什么是JavaScript解构赋值_解构赋值有哪些实用技巧
Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】
如何在搬瓦工VPS快速搭建网站?
深圳网站制作的公司有哪些,dido官方网站?
如何快速打造个性化非模板自助建站?
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
如何用AWS免费套餐快速搭建高效网站?
如何确保FTP站点访问权限与数据传输安全?
微信小程序制作网站有哪些,微信小程序需要做网站吗?
三星、SK海力士获美批准:可向中国出口芯片制造设备
中国移动官方网站首页入口 中国移动官网网页登录
如何快速搭建高效WAP手机网站?
个人摄影网站制作流程,摄影爱好者都去什么网站?
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
七夕网站制作视频,七夕大促活动怎么报名?
北京网站制作公司哪家好一点,北京租房网站有哪些?
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
,南京靠谱的征婚网站?
Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比
5种Android数据存储方式汇总
Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程
Laravel怎么连接多个数据库_Laravel多数据库连接配置
*服务器网站为何频现安全漏洞?
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
免费视频制作网站,更新又快又好的免费电影网站?
原生JS获取元素集合的子元素宽度实例
如何在阿里云部署织梦网站?

