摘要:用C/S結構開發的網絡軟件,要解決的主要問題之一就是客戶端的自動升級,只有完成了這一功能,才能使開發的網絡軟件能及時更新與完善。在Delphi中,通過對比當前版本和最新版本的客戶端程序的修改時間來決定是否升級客戶端,利用Delphi的TIdTCPClient,TIdUDPServer,TIdTCPServer,TIdUDPClient等網絡通訊控件來完成客戶端程序的的傳輸與升級。
關鍵詞:自動升級;基本原理;客戶端;服務器
中圖分類號:TP311文獻標識碼:A 文章編號:1009-3044(2008)09-11662-04
How Discusses the Delphi Procedure to Realize the Automatic Promotion Shallowly
FU Xin-juan
(Victory petroleum administrative bureau victory hospital informationcenter microcomputer room,Dongying 257055 China)
Abstract: With the C/S structure development's network software, one which of subject matters must solve is the client side automatic promotion, only then has completed this function, can enable the development the network software to renew and the consummation promptly. In Delphi, through the contrast current edition and the newest edition's client side procedure's revision time decided whether to promote the client side, uses Delphi TIdTCPClient, TIdUDPServer, TIdTCPServer, network communications and so on TIdUDPClient controls completes the client side procedure the transmission and the promotion.
Key words: Automatic promotion; Basic principle; Client side; Server
1 引言
現在的許多網絡軟件都實現了自動升級功能,從各種殺毒軟件,到QQ、UC這樣的即時通訊軟件,都有這方面的功能。這一功能的實現可以使程序不用人工干預,自動完成程序的升級與更新。在開發網上辦公系統的過程中,由于采用C/S結構,客戶端經常需要更新,通過對這些網絡軟件的分析,掌握了軟件自動升級的基本原理,在Delphi中輕松得以實現。
2 實現的基本原理
自動升級的實現需要由客戶端和服務器兩部分來完成,客戶端在啟動時,先判斷本地升級目錄中的客戶端程序的修改時間是否和正在運行的客戶端程序的修改時間一致,如果不一致,就運行升級程序完成升級。客戶端運行后定時檢測服務器,如果有新程序,就下載到本地升級目錄中,等待下次啟動時完成升級。
3 具體的實現方法
客戶端在運行后,就動態檢測服務器端應用程序的發布情況,一發現有新的客戶端程序發布,就及時下載升級。
3.1 客戶端的實現代碼
(1)在Delphi中新建客戶應用程序,在其工程文件中判斷當前程序是否和升級目錄程序的修改時間一致,若是不一致,就運行客戶端升級程序upgrade.exe。
msgclient.dpr中的核心代碼:
program msgclient;
uses
……
{$R *.RES}
Var
upfilename,newfilename,filename:string;
upfiletime,newfiletime:integer;
begin
……
//如果升級目錄upgrade中有最新版本的客戶端程序,則啟動軟件升級程序upgrade.exe,并退出。
upfiletime :=0;
newfiletime :=0;
upfilename:=ExtractFilePath(paramstr(0))+'upgrade\etoffice.exe' ;
newfilename:=ExtractFilePath(paramstr(0))+'netoffice.exe';
if fileexists(upfilename) then
upfiletime:=fileage(upfilename);
newfiletime:=fileage(newfilename);
filename:=ExtractFilePath(paramstr(0))+'upgrade.exe';
if (upfiletime<>newfiletime) and (upfiletime<>0) then
begin
winexec(pchar(filename),SW_SHOWNORMAL);
exit;
end;
……
end.
(2)新建應用,命名為upgrade,用于升級本地客戶端程序,在工程文件upgrade.dpr中用函數FindWindow(nil,'NetOffice_Fxj')獲得客戶端程序的主窗口句柄,再判斷升級目錄中是否有升級后的客戶端軟件,若存在就用函數SendMessage(WsbgHWnd,WM_CLOSE,0,0)關閉客戶端程序,用函數copyfile(pchar(upfilename),pchar(newfilename),False)把升級目錄中客戶端程序復制到當前目錄并運行。
關鍵代碼:
program upgrade;
uses
……
{$R *.RES}
Var
WsbgHWnd : HWnd;
upfilename,newfilename:string;
begin
//獲得當前客戶端程序的文件句柄。
WsbgHWnd := FindWindow(nil,'NetOffice_Fxj');
upfilename:=ExtractFilePath(paramstr(0))+'upgrade\etoffice.exe' ;
newfilename:=ExtractFilePath(paramstr(0))+'netoffice.exe';
if fileexists(upfilename) then
begin
if WsbgHWnd <>0 then
begin
SendMessage(WsbgHWnd ,WM_CLOSE,0,0);
end;
deletefile(newfilename);
Application.MessageBox('系統已更新。','信息',MB_OK+MB_ICONINFORMATION);
copyfile(pchar(upfilename),pchar(newfilename),False);
WinExec(pchar(newfilename),SW_SHOWNORMAL);
exit;
end;
application.Terminate;
Application.Initialize;
Application.Run;
end.
(3)客戶端軟件在啟動時向服務器端發送升級檢測命令,及本地客戶端的修改時間,服務器端在收到信息后和服務器端升級目錄中的客戶端程序的修改時間作對比,若不一致,就發送升級后的客戶端程序。
在客戶端程序的主窗體中加入TIdTCPServer控件和TIdUDPServer控件。在TIdUDPServer控件的OnUDPRead事件中加入如下代碼,用全局變量upgradetime獲得升級后客戶端程序的修改時間。
{rec:TString變量,接收服務器發送的信息。}
if rec.Values['cmd']='upgrade' then
begin
upgradetime:=strtoint(rec.Values['upfiletime']);
end;
在TIdTCPServer控件的OnExecute事件中加入如下代碼,用于接收服務器端發送的最新版本的客戶端程序:
procedure TFrm_main.TCPServerExecute(AThread: TIdPeerThread);
var
MYFStream:TFileStream;
filename,ssr:string;
newfile:integer;
sr: TSearchRec;
begin
//接收服務器端發來的信息。
filename:=AThread.Connection.ReadLn;
if filename<>'' then
begin
filename:=extractfilepath(paramstr(0)) + filename;
ssr:=extractfilepath(filename);
StrLCopy(Pchar(ssr),pchar(ssr),Length(ssr)-1);
if FindFirst(ssr, faDirectory, sr) <>0 then
MkDir (extractfilepath(filename));
MyFStream := TFileStream.Create(filename, fmCreate);
Try
AThread.Connection.ReadStream(MyFStream,-1,True);
finally
AThread.Connection.Disconnect;
MYFStream.Free;
FindClose(sr);
end;
if upgradetime<>0 then
begin
newfile:=FileOpen(filename,fmOpenWrite);
FileSetDate(newfile,upgradetime);
FileClose(newfile);
upgradetime:=0;
end;
end;
end;
3.2 服務器端的實現代碼
服務器端在收到客戶端發送的升級檢測命令及客戶端程序的修改時間后,把收到的客戶端程序的修改時間和服務器端升級目錄中的修改時間作對比,如果不一致,就把升級目錄中的客戶端程序發送到客戶端。
在服務器的主窗體中加入TIdTCPClient控件和TIdUDPServer控件,在TIdUDPServer控件的OnUDPRead事件中加入如下代碼完成這一功能。
{ rec:TString變量,接收客戶端發送的信息,若接收到的信息為“upgrade”,則執行升級代碼。}
if rec.Values['cmd']='upgrade' then
begin
//服務器端的升級目錄中有最新版的客戶端程序時,把它發送到客戶端。
if FileExists(ExtractFilePath(paramstr(0))+'upgrade\etoffice.exe') then
begin
newfiletime:=FileAge(ExtractFilePath(paramstr(0))+'upgrade\etoffice.exe');
if inttostr(newfiletime)<>rec.Values['upfiletime'] then
begin
newfilename:='upgrade\etoffice.exe';
TCPClient.Host:=ABinding.PeerIP;
Try
TCPClient.Connect;
TCPClient.Writeln(newfilename);
newfilename:=extractfilepath(paramstr(0))+newfilename;
Fm := TfileStream.Create(newfilename,fmsharedenywrite);
TCPClient.OpenWriteBuffer;
TCPClient.WriteStream(Fm);
TCPClient.CloseWriteBuffer;
Finally
TCPClient.Disconnect;
Fm.Free;
End;
rec.Values['upfiletime']:=inttostr(newfiletime);
TmpStr := rec.text;
Binding.SendTo(ABinding.PeerIP,RemoteUDPport,TmpStr[1],length(TmpStr));
end;
end;
end;
4 結束語
這里只簡單介紹了完成軟件自動升級的基本方法和實現的核心代碼,在自己的軟件中可以進行擴充和完善。只要細心研究,許多商業軟件能完成的功能,也能在自己開發的軟件中實現。
參考文獻:
[1] 肖建.Delphi 6編程基礎[M].北京:清華大學出版社,2001.
[2] 曹智威.Delphi6實用編程技術[M]. 北京: 水利水電出版社,2002.
[3] 黃建華.Delphi程序設計[M].清華大學出版社,北京,1997.