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.
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!