最近在研究軟件的自動更新功能,手動更新太麻煩而且對電腦小白來說容易出錯。之前對自動更新沒什么概念,不知道如何實現。簡單百度之后,原來“更新”功能是一個單獨的模塊,在需要更新的時候啟動這個模塊,然后將主程序的相關文件更新,以達成更新主程序功能的目的。那么,有兩個問題:1.什么時候啟動更新?2.如何更新主程序的相關文件?
我的思路是:在服務器某個位置放置一個文件,這個文件里存放了需要更新文件的列表以及一個類似版本號的標識。主程序每次啟動的時候 如果是聯網狀態下,就去讀取這個文件中的“版本標識”來和自身的版本標識比較,如果自身的版本標識低於站點的這個標識就啟動更新程序,獲取列表中所表明的需要更新的文件,存放到指定位置即可完成更新。那么如何獲取這些文件呢?應該是要使用下載功能。
文件列表和版本號這個好實現,最不濟弄個txt文件存儲,然后解析一下就行。下載這個功能比較麻煩,C#的http命名空間里有下載功能的類,不太好用,雖然沒怎么深入研究過。當然,我是小白一個,再怎么深入研究也玩不出什么花來,就想吃現成的。網上瘋狂搜羅一番,發現迅雷雲加速開放平台比較對我的胃口,就它了。不過可惜的是,正式的SDK申請已經在3年前暫停了,看樣子也沒有恢復申請的跡象。不過好在還有個試用版的SDK可以用,對付我這個小功能應該是綽綽有余了。好在我當時順手把這個試用版的SDK保存下來了,不然我現在能悔死,因為現在整個下載頁面都打不開了。
材料有了,怎么用又是個問題。接口代碼全是C/C++,而我用的是C#!SDK壓縮包里提供了一個更新日志txt文件、一個xldl.dll文件、一個xldl.h文件還有一個download文件夾。真正可以直接交互的就是xldl.dll動態鏈接庫,xldl.h文件定義了需要用的的一些類型。居然沒有示例文檔!!!雖然我的水平爛到你把文檔給我了我也未必能看懂,但是你不給我,那我就真是抓瞎了。網上兜兜轉轉找到一個“基礎教程”壓縮包,里面是個word文檔,有一段完整的示例代碼。如獲至寶,趕緊下載下來。文檔一個5頁,代碼占了3頁,示例截圖占1頁,說明文字占1頁。信息量忒少了點,不過好過沒有。完整代碼如下:
#include"stdafx.h" #include<Windows.h> #include<iostream> #include<stdio.h> #include<tchar.h> #include<tchar.h> #include<Shlwapi.h> #include"assert.h" #pragmacomment(lib,"shlwapi.lib") #include"xldl.h" voidDownloadFile(DownWrapper* pWapper,conststd::wstring&wstrUrl,conststd::wstring&wstrFilename,conststd::wstring&wstrSavePath); int_tmain(intargc, _TCHAR* argv[]) {
assert(argc>= 3); WCHARszModulePath[MAX_PATH] = {0}; ::GetModuleFileName(NULL, szModulePath, MAX_PATH); ::PathRemoveFileSpec(szModulePath); WCHARszDllpath[MAX_PATH] = {0}; ::PathCombine(szDllpath, szModulePath, L"xldl.dll"); //查找xldl.dll,並加載該dll 1 DownWrapper* pWapper = newDownWrapper(szDllpath); if (!pWapper->Init()) //初始化下載引擎 2 { std::cout<<"Error, Init Failed!"<<std::endl; return 1; } std::wstringwstrUrl(argv[1]); std::wstringwstrSavePath(argv[2]); std::wstringwstrFileName(argv[3]); DownloadFile(pWapper, wstrUrl, wstrFileName, wstrSavePath); Sleep(600000); pWapper->UnInit(); //卸載下載引擎 7 return 0; } voidDownloadFile( DownWrapper* pWapper,conststd::wstring&wstrUrl,conststd::wstring&wstrFilename,conststd::wstring&wstrSavePath) { //初始化新建任務參數 DownTaskParampara; memcpy(para.szTaskUrl, wstrUrl.c_str(), wstrUrl.length()*sizeof(WCHAR)); std::wstringwstrRefUrl = L""; memcpy(para.szRefUrl, wstrRefUrl.c_str(), wstrRefUrl.length()*sizeof(WCHAR)); memcpy(para.szFilename, wstrFilename.c_str(), wstrFilename.length()*sizeof(WCHAR)); memcpy(para.szSavePath, wstrSavePath.c_str(), wstrSavePath.length()*sizeof(WCHAR)); //新建任務 HANDLEhTask = pWapper->TaskCreate(para);//3 std::cout<<"Create New Task"<<std::endl; if (hTask) { std::cout<<"Now Start Task"<<std::endl; pWapper->TaskStart(hTask); //開始任務 4 } else { std::cout<<"Create Task Filed!"<<std::endl; return ; } DownTaskInfoinfo; while(true) {
Sleep(1000); pWapper->TaskQuery(hTask, info); //輪詢任務信息 5 std::cout<<"Size: "<<info.nTotalSize<<", Percent: "<<info.fPercent<<", Speed: "<<info.nSpeed<<std::endl; if (info.stat == TSC_COMPLETE) { std::cout<<"Total File Size: " <<info.nTotalSize<<std::endl; std::cout<<"Task Success!"<<std::endl; break; } if (info.stat == TSC_ERROR) { std::cout<<"Task Failed!"<<std::endl; break; } } pWapper->TaskDelete(hTask); //刪除任務,釋放任務占用內存 6 }