做winform的程序,不管用沒用過自動(dòng)更新,至少都想過自動(dòng)更新是怎么實(shí)現(xiàn)的.
我這里共享一個(gè)自動(dòng)更新的一套版本,給還沒下手開始寫的人一些幫助,也希望有大神來到,給指點(diǎn)優(yōu)化意見.
本初我是通過socket來傳輸文件的,后來因?yàn)閭鞔笪募霈F(xiàn)異常,前期又沒有定義比較好的協(xié)議,后來就改用webservices了.
自動(dòng)更新分三個(gè)部分,服務(wù)端(webservice服務(wù),配置與更新),配置客戶端(或叫發(fā)布客戶端),客戶端(主程序)
服務(wù)端:
ConfigServer.asmx
因?yàn)榇a共享了,就不傳代碼了,發(fā)個(gè)截圖吧.

負(fù)責(zé)與配置客戶端交互,對(duì)文件的發(fā)布(軟件上傳),及版本維護(hù).
這里為了考慮大文件的問題,每次上傳是分包傳送的.UploadFileModel 是分包的定義,這個(gè)由配置端來決定分包值.
public class UploadFileModel { string _RelativePath; /// <summary> /// 相對(duì)路徑 /// </summary> public string RelativePath { set { _RelativePath = value; } get { if (_RelativePath != string.Empty && _RelativePath.Substring(_RelativePath.Length - 1) != "http://") { _RelativePath += "http://"; } return _RelativePath; } } /// <summary> /// 文件名 /// </summary> public string FileName { set; get; } /// <summary> /// 文件流 /// </summary> public byte[] FileStream { set; get; } /// <summary> /// 開始該文件位置 /// </summary> public int StartPosition { set; get; } /// <summary> /// 是否完成該文件的傳送了 /// </summary> public bool IsFinish { set; get; } /// <summary> /// 整個(gè)文件流的長度 /// </summary> public long FileStreamLength { set; get; } /// <summary> /// 文件的最后更新時(shí)間 /// </summary> public DateTime FileLastTime { set; get; } /// <summary> /// 當(dāng)前是第幾包 /// </summary> public int CurrentPackIndex { set; get; } /// <summary> /// 總共第幾包 /// </summary> public int MaxPackIndex { set; get; } }考慮上傳的文件內(nèi)容有可能含子文件夾,這里有相對(duì)路徑的配置.
UpdateServer.asmx 負(fù)責(zé)與客戶端交互,用于下載需要更新的文件.
有兩個(gè)服務(wù),GetFileList 獲取文件列表,與本地文件通過版本號(hào)篩選出要更新的文件信息.
GetFile 用于更新文件,RequestFileModel 定義了要請(qǐng)求文件的指定長度的文件流(其實(shí)也是可以按分包來下載,具體怎么分包是有客戶端來定義)
public class RequestFileModel { /// <summary> /// 文件id /// </summary> public long FileId { set; get; } /// <summary> /// 開始該文件位置 /// </summary> public int StartPosition { set; get; } /// <summary> /// 讀取文件流的長度(一次讀取多少字節(jié)) /// </summary> public int ReadFileLength { set; get; } }
配置客戶端:

主界面操作比較簡(jiǎn)單,需要注意的就是發(fā)布的時(shí)候是選擇一個(gè)發(fā)布文件夾,要發(fā)布的文件由該文件夾指定,因?yàn)橐@取相對(duì)路徑.

上傳文件的具體流程代碼就不發(fā)了,下載源碼自己看吧,分包的發(fā)送,不過是計(jì)算出每次發(fā)送的字節(jié),告訴服務(wù)器發(fā)了多少,是不是完成了.
更新客戶端:

我這寫的更新客戶端比較簡(jiǎn)單而已不是自動(dòng),需要手動(dòng)點(diǎn)擊,這個(gè)根據(jù)需求可以稍微改一下,或者干脆不用這個(gè)界面,因?yàn)樯蟼鞯南嚓P(guān)操作已經(jīng)封裝起來了.
本地文件信息我是通過一個(gè)FileInfo.data的文件來記錄的.
關(guān)于app.config里面有三個(gè)配置項(xiàng).

DownloadPath 是更新的文件放到哪個(gè)文件夾下.
UpdateServerUrl 是webservices的服務(wù)地址.
MainApp 更新完成之后需要更新的主程序,通過PRocess.Start()方法來調(diào)用.
當(dāng)所有文件下載完成后,會(huì)把FileInfo.data 文件信息更新.
最后總結(jié)一下自動(dòng)更新的整體流程:
1.訪問更新服務(wù),獲取所有文件信息.
2.比較服務(wù)器文件信息,與本地文件信息做比較,篩選出需要下載的文件信息;
3.下載需要更新的文件,保存至指定目錄下.
4.如果指定目錄存在,將指定目錄下的文件替換現(xiàn)有程序文件,刪除已更新的文件夾及所有文件,然后啟動(dòng)主程序;
5.啟動(dòng)主程序,并替換更新程序(如果需要更新的話,更新程序會(huì)起別名放于相同目錄下)
共享代碼里webservices端有兩個(gè)類庫,這個(gè)數(shù)據(jù)操作,配置內(nèi)容是放到sqlite庫中的,這兩個(gè)類庫可在bin下找到.

源碼下載
突然看到一個(gè)很不錯(cuò)的自動(dòng)升級(jí)項(xiàng)目,來給大家分享一下, https://github.com/iccfish/FSLib.App.SimpleUpdater
文件上傳下載是基于http,配置及使用看起來很成熟全面.
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注