Delphi 实现软件自动升级的功能
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-ybde.txt
main=Project1.exe:是主程序名称,和升级程序在同一目录
param={app}sayyes.pj2-ybde.txt:这是命令行参数,app为当前路径,在程序中替换掉,传递给主程序(如果需要的话)
update.ini的内容格式如下
[root]
办事处查询.txt=20100519
[dbcard]
sayyes.pj2=20100519
FTP用户密码.txt=20100519
[root]代表根目录,后面的[dbcard]代表子目录,依次类推
unitMain;
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;
procedureIdFTP1Work(Sender:TObject;AWorkMode:TWorkMode;
constAWorkCount:Integer);
procedureIdFTP1WorkEnd(Sender:TObject;AWorkMode:TWorkMode);
procedureFormCreate(Sender:TObject);private
{Privatedeclarations}
FSize:Integer;
FPath:string;
FExePath:string;
FInitPath:string;
FIniFile:TIniFile;
FHandle:HWND;
FMainExe:string;
FParam:string;
procedureCheckUpdateList;
functionConnectFTP:Boolean;
procedureDownLoadFile;
procedureLoadIni;
procedureSaveIni;
public
{Publicdeclarations}
end;
var
frmMain:TfrmMain;
implementation
uses
Flash;
{$R*.dfm}
//下载进度
procedureTfrmMain.IdFTP1Work(Sender:TObject;AWorkMode:TWorkMode;
constAWorkCount:Integer);
begin
ProgressBar1.Position:=AWorkCount;
Application.ProcessMessages;
end;
procedureTfrmMain.IdFTP1WorkEnd(Sender:TObject;AWorkMode:TWorkMode);
begin
ProgressBar1.Position:=0;
ProgressBar2.StepBy(1);
end;
procedureTfrmMain.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;
//检查更新列表
procedureTfrmMain.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);
ifFileExists(FExePath+'update.ini')=FalsethenExit;
oldFile.LoadFromFile(FExePath+'update.ini');
newFile.LoadFromFile(FExePath+'update_new.ini');
itempath:='';
//下面开始比较两个list,如果newFile的版本号大于oldFile的版本号或者oldFile中没有的都表示要更新的
fori:=0tonewFile.Count-1do
begin
itemstr:=newFile.Strings[i];
ifitemstr=''thenContinue;
ifitemstr[1]='['then
begin
itempath:=Copy(itemstr,2,Length(itemstr)-2);
//如果是根目录
ifitempath='root'then
itempath:='/';
Continue;
end;
itemstr:=newFile.Names[i];
index:=oldFile.IndexOfName(itemstr);
ifindex=-1then
begin
item:=list_file.Items.Add;
item.Caption:=itemstr;
item.SubItems.Add(itempath)
end
else
begin
ver:=StrToIntDef(newFile.Values[itemstr],0);
ifver>StrToIntDef(oldFile.Values[itemstr],0)then
begin
item:=list_file.Items.Add;
item.Caption:=itemstr;
item.SubItems.Add(itempath);
end;
end;
end;
iflist_file.Items.Count=0thenApplication.Terminate;
finally
oldFile.Free;
newFile.Free;
end;
end;
functionTfrmMain.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;
//下载文件更新
procedureTfrmMain.DownLoadFile;
var
i:Integer;
path:string;
s1,s2:String;
begin
ProgressBar2.Max:=list_file.Items.Count;
ProgressBar2.Position:=0;
FIniFile.EraseSection('error');
fori:=0tolist_file.Items.Count-1do
begin
Label4.Caption:='正在下载'+list_file.Items[i].Caption;
Application.ProcessMessages;
IdFTP1.ChangeDir(FInitPath);
path:=list_file.Items[i].SubItems.Strings[0];
ifpath<>'/'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;
procedureTfrmMain.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;
procedureTfrmMain.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.
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!