天天看點

用PB實作用戶端程式的自動更新

C/S結構的運作模式雖然沒有B/S結構更加容易擴充和簡便,但由于其穩定性好、安全性高、運作速度快等特點,現在仍然被廣泛應用于各種大型應用系統中,有些則和B/S形成混合的運作模式。

  B/S優越于C/S的一個很大特點就是,用戶端不需要安裝用戶端軟體,通過浏覽器就可以實作各種應用,并且伺服器上的内容的變化可以快速反映到用戶端。如果讓用戶端軟體也實作自動更新,可以彌補C/S模式在這方面的缺陷。本文就給出了一種可自動更新用戶端軟體的設計思路,并給出了使用PB的實作方法。

1 實作思路

  整個軟體結構包括:更新資料庫伺服器、更新代理程式、用戶端應用程式、更新服務管理程式等。更新資料庫器儲存各個版本軟體的版本、檔案名、檔案内容等資訊;更新代理程式負責讀取更新資料庫伺服器中的最新版本資訊和檔案資訊,完成最新版本下載下傳和更新,并啟動用戶端應用程式;用戶端應用程式為用戶端具體應用的程式軟體,即為需要實作更新的軟體;最新版本上載程式是更新資訊管理程式,用于上傳最新的版本資訊和相應的檔案内容。整體結構如圖1所示。

圖1 自動更新的軟體實作方案

  用戶端應用程式運作之前,先啟動一個更新代理程式,該代理從更新資料庫伺服器中讀取更新資訊,如果存在最新版本,提示使用者并決定是否下載下傳最新版本,然後并啟動用戶端應用程式。

  更新資訊使用如下資料表(soft_fileinfo)進行維護和管理,檔案版本号儲存檔案的版本資訊,檔案名和檔案内容儲存檔案的名稱和檔案的二進制内容。建立改變的SQL語句如下(ASA7資料庫):

CREATE TABLE dba.soft_fileinfo(

version char(14) NOT NULL, //檔案版本号

filename char(30) NOT NULL, //檔案名

filedata long binary, //檔案内容

PRIMARY KEY (version, filename)); //以檔案版本号和檔案名為主鍵

  下面給出PB中的程式實作方法,假設用戶端應用程式執行檔案名為"sale.exe",更新資料庫伺服器采用ASA7。

2 用戶端更新代理程式實作

  在PB中建立一個應用,在應用的執行個體變量中聲明:

string old_version

declare get_new_filename cursor for

select filename

from dba.soft_fileinfo

where version > :old_version;

在Open事件中編寫如下代碼:

string ls_newversion

//連接配接更新伺服器,這裡我們用ASA7資料庫代替更新資料庫伺服器

SQLCA.DBMS = "ODBC"

SQLCA.AutoCommit = False

SQLCA.DBParm = "ConnectString='DSN=EAS Demo DB V4;UID=dba;PWD=sql', ConnectOption='SQL_DRIVER_CONNECT,SQL_DRIVER_NOPROMPT'"

connect using sqlca;

if sqlca.sqlcode = 0 then

//讀取本地版本号

RegistryGet("HKEY_LOCAL_MACHINE/Software/MySoftware/sale", "Version", RegString!, old_version)

//讀取更新伺服器上的最新版本号

select max(version) into :ls_newversion

from dba.soft_fileinfo;

//如果更新伺服器上的最新版本号大于本地版本号,提示下載下傳最新程式

if old_version < ls_newversion then

if MessageBox("注意","存在最新版本程式,是否立即更新?",Question!,YesNo!) = 1 then

//下載下傳最新程式

string ls_filename

blob lb_filedata

blob lb_tempdata

long max_len = 32765

long ll_len

//通過遊标,得到所有需要更新的檔案名,然後分别處理

open get_new_filename;

fetch get_new_filename into :ls_filename;

do while (sqlca.sqlcode = 0)

//得到最新版本的相應檔案内容

selectblob filedata into :lb_filedata

from dba.soft_fileinfo

where filename = :ls_filename

order by version desc;

long ll_file,loops,i

//删除舊版本檔案

FileDelete(ls_filename)

//建立新的檔案

ll_file = FileOpen(ls_filename,StreamMode!,Write!,LockReadWrite!, Append!)

ll_len = len(lb_filedata)

//由于PB中的FileWrtie一次隻能寫入32765大小的檔案,是以必須分多次讀寫

IF ll_len > max_len THEN

IF Mod(ll_len, max_len) = 0 THEN

loops = ll_len/max_len

ELSE

loops = (ll_len/max_len) + 1

END IF

ELSE

loops = 1

END IF

FOR i = 1 to loops

lb_tempdata = BlobMid(lb_filedata,(i - 1)*max_len + 1,max_len)

FileWrite(ll_file,lb_tempdata)

NEXT

FileClose(ll_file)

//讀取下一個檔案内容

fetch get_new_filename into :ls_filename;

loop

close get_new_filename;

end if

end if

else

MessageBox("錯誤","沒有成功連接配接更新伺服器")

end if

//運作應用程式

Run("sale.exe")

3 更新服務管理程式實作

  更新服務管理程式的實作實際就是一個維護soft_fileinfo表的應用程式,可以修改版本資訊,也可以添加新的版本資訊和檔案内容。這一部分思路比較簡單,這裡不再給出所有具體的程式代碼,僅給出PB将新版本檔案寫入資料庫的方法。

integer li_FileNum, loops, i

long flen, bytes_read, new_pos

blob b, tot_b

//得到目前選擇的檔案的内容大小,sle_filename包含檔案所在路徑及檔案名

flen = FileLength(sle_filename.Text)

//打開檔案

li_FileNum = FileOpen(sle_filename.Text,StreamMode!, Read!, LockRead!)

//由于FileRead函數一次隻能讀出32765大小的資料,是以先計算讀取次數

IF flen > 32765 THEN

IF Mod(flen, 32765) = 0 THEN

loops = flen/32765

ELSE

loops = (flen/32765) + 1

END IF

ELSE

loops = 1

END IF

new_pos = 1

//分多次讀出檔案中的所有資料,放在tot_b變量中

FOR i = 1 to loops

bytes_read = FileRead(li_FileNum, b)

tot_b = tot_b + b

NEXT

//關閉檔案

FileClose(li_FileNum)

修改目前版本的檔案内容

updateblob dba.soft_fileinfo

set filedata = :tot_b

where version = current_version;

//如果儲存成功,遞交資料庫

IF sqlca.SQLNRows > 0 THEN

COMMIT;

else

rollback;

messagebox("錯誤","檔案内容儲存失敗!")

END IF

文章引用自: