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; TfrmMain = class(TForm) IdFTP1: TIdFTP; IdHTTP1: TIdHTTP; ProgressBar1: TProgressBar; GroupBox1: TGroupBox; ld_host: TLabeledEdit; ld_username: TLabeledEdit ld_psabelw: TLabel dit; TComboBox; ProgressBar2: TProgressBar; Label3: TLabel; list_file: TListView; Label4: TLabel; procedure IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); procedure Work1C; FormCreate(Sender: TObject); private { Private declarations } FSize:Integer; FPath: string; FExePath: string; FInitPath: string; FIniFile:TIniFile; FHandle:HWND; FMainExe:string; FParam: string; Boolean; procedure DownLoadFile; : Integer); begin ProgressBar1.Position := AWorkCount; Application.ProcessMessages; end; procedure TfrmMain.IdFTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode); begin ProgressBar1.Position := 0; ProgressBar2.Step.M : 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; //先下載伺服器上的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., [itemstr. > 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.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。 IdFTP1.Connect; IdFTP1.Passive := cb_mode.ItemIndex = 1; FInitPath := IdFTP1.RetrieveCurrentDir; Result := IdFTP1.Connected; except Result := False; end; end; //下載檔案更新; ,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 :ForceDirectories(FExePath+path); 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; 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.
如有疑問請留言或到本站社區交流討論,感謝閱讀,希望能幫助大家,謝謝大家對本站的支持!