目前我的工作是用C#開(kāi)發(fā)一個(gè)桌面軟件,安裝到分布各地的數(shù)以百計(jì)的PC上,而且軟件的修改和升級(jí)在未來(lái)很長(zhǎng)一段時(shí)間內(nèi)都很頻繁,所以采用了微軟的ClickOnce部署技術(shù)。這是一種上手很快使用方便的技術(shù),但是你在決定把它應(yīng)用在一個(gè)真正的商業(yè)項(xiàng)目中之前,應(yīng)該了解一些將來(lái)可能會(huì)困擾你的問(wèn)題,然后再判斷一下是不是應(yīng)該采用它。也許自己從頭寫(xiě)一個(gè)自動(dòng)升級(jí)框架反而更適合你的情況。
1,無(wú)法有效避免非法的下載
使用ClickOnce部署,你的軟件的更新版可以發(fā)布到Web服務(wù)器上,當(dāng)用戶(hù)從開(kāi)始菜單啟動(dòng)軟件時(shí),ClickOnce自動(dòng)到指定的URL去檢測(cè)是否存在新版本,并且從這個(gè)地址下載最新版本。問(wèn)題在于,訪問(wèn)這個(gè)URL的過(guò)程是ClickOnce的內(nèi)部機(jī)能,不和用戶(hù)產(chǎn)生任何交互,也就沒(méi)法進(jìn)行有效的用戶(hù)驗(yàn)證,要想ClickOnce正常更新,就必須保證這個(gè)URL能夠任意訪問(wèn)。導(dǎo)致任何人只要在瀏覽器輸入這個(gè)URL,就可以下載程序。
我沒(méi)有找到好的解決方法,只能盡量加強(qiáng)軟件本身的驗(yàn)證機(jī)制,即使有人非法下載安裝了你的程序,讓他無(wú)法使用也就罷了。
2,.NET Framework安裝的煩惱
使用ClickOnce可以自動(dòng)驗(yàn)證客戶(hù)端PC是否安裝了必需的.NET Framework以及其版本,并且可以自動(dòng)啟動(dòng)一個(gè)下載程序從微軟網(wǎng)站取得最新的安裝文件。這是一個(gè)很有用的功能,一般情況下很難說(shuō)服用戶(hù)先去微軟網(wǎng)站自己安裝.NET Framework,大多數(shù)用戶(hù)甚至根本不想知道什么是Framework(很難和他們解釋清楚,為什么安裝一個(gè)很小的軟件,需要先安裝一個(gè)幾百兆大的叫做Framework的鬼東西)。然而在實(shí)際測(cè)試中發(fā)現(xiàn)了一個(gè)問(wèn)題,用戶(hù)的PC在公司內(nèi)部通過(guò)代理才能訪問(wèn)互聯(lián)網(wǎng),不知什么原因,自動(dòng)下載程序訪問(wèn)微軟網(wǎng)站的速度慢到無(wú)法接受的程度,大約200M的Framework,60個(gè)文件,自動(dòng)安裝整整花費(fèi)了一個(gè)多小時(shí),遠(yuǎn)遠(yuǎn)不如自己直接下載安裝包手動(dòng)安裝來(lái)的快。
幸好ClickOnce提供了一個(gè)選項(xiàng),你可以把Framework和程序同時(shí)發(fā)布到自己的服務(wù)器上---但是,由于Visual Studio 2008的一個(gè)小Bug,這個(gè)選項(xiàng)是不好用的,你需要首先參考【Visual Studio 2008 Service Pack 1 (SP1) Realease Note】這個(gè)文檔的2.3.1.1章節(jié),手動(dòng)修復(fù)這個(gè)小問(wèn)題---現(xiàn)在你可以把Framework也發(fā)布到同一臺(tái)服務(wù)器上進(jìn)行下載了,只要你對(duì)自己服務(wù)器的速度有信心。
目前ClickOnce的下載機(jī)能不是很智能,不能斷點(diǎn)續(xù)傳:我這邊碰到的一個(gè)情況就是由于服務(wù)器端的某代理軟件的吞吐量不夠,下載過(guò)程中失敗的幾率很高;另外如果是分布在多個(gè)地域的用戶(hù),不一定從哪里下載比較快,可能有的人反而訪問(wèn)微軟官方網(wǎng)站比較快,但是ClickOnce并沒(méi)有辦法動(dòng)態(tài)切換Framework下載地址。問(wèn)題的關(guān)鍵是這個(gè)Framework自動(dòng)下載安裝的過(guò)程,沒(méi)法靈活干預(yù),只有在最理想的網(wǎng)絡(luò)環(huán)境中才能真正發(fā)揮其優(yōu)點(diǎn)。
3,.NET Framework安裝的另一個(gè)煩惱
解決了上面的問(wèn)題,我已經(jīng)把軟件和.NET Framework都部署在Web服務(wù)器上,鼠標(biāo)一點(diǎn),似乎一切都順利。然而隨著安裝軟件的用戶(hù)數(shù)越來(lái)越多,自動(dòng)安裝過(guò)程中發(fā)生莫名錯(cuò)誤
的投訴電話(huà)也越來(lái)越多。問(wèn)題的原因在于,有些PC里面已經(jīng)安裝過(guò)不同版本Framework3.5SP1,但是又和我發(fā)布的版本不盡相同,比如沒(méi)有語(yǔ)言包等等,ClickOnce沒(méi)有辦法自動(dòng)覆蓋安裝。
Framework安裝版本沖突的問(wèn)題其實(shí)很常見(jiàn),一般性的解決辦法就是從控制面板刪除現(xiàn)有的版本之后重啟計(jì)算機(jī),再重新安裝即可。仍然不行的話(huà)可以借助微軟官方提供的.NET Framework Cleanup工具徹底刪除既存版本。但是這種解決方式對(duì)于最終用戶(hù)來(lái)說(shuō)不可接受,他們需要的是真正的ClickOnce:點(diǎn)擊一下,幫我解決所有問(wèn)題。
早知今日后悔當(dāng)初,不該給用戶(hù)一個(gè)過(guò)高的期望值,從一開(kāi)始就教育他們老老實(shí)實(shí)的手動(dòng)安裝Framework就好了。
4,安裝目錄和卸載
軟件投入使用后,用戶(hù)投訴說(shuō),每次版本升級(jí),都會(huì)經(jīng)過(guò)很長(zhǎng)時(shí)間的停頓才能看到程序的啟動(dòng)畫(huà)面。調(diào)查之后發(fā)現(xiàn):ClickOnce部署的程序會(huì)安裝在C:\Documents and Settings\用戶(hù)名\Local Settings\Apps\2.0文件夾下的一個(gè)隨機(jī)生成的目錄中。版本升級(jí)的時(shí)候,并不會(huì)直接把老版本刪除,而是會(huì)隨機(jī)生成另外一個(gè)目錄,并且將現(xiàn)有的用戶(hù)數(shù)據(jù)文件原封不動(dòng)的復(fù)制過(guò)去。如果需要,可以在【控制面板-添加安裝程序】中恢復(fù)到老的版本繼續(xù)使用。程序卸載的時(shí)候,這個(gè)目錄會(huì)自動(dòng)被清空。
問(wèn)題在于,我的這個(gè)軟件啟動(dòng)后生成保存了數(shù)百個(gè)XML格式的模板文件和數(shù)據(jù)文件,大量小文件的磁盤(pán)復(fù)制操作非常耗時(shí)。開(kāi)發(fā)和測(cè)試用的PC性能較好停頓還不太明顯,不湊巧用戶(hù)使用的是比較舊的筆記本電腦,結(jié)果版本升級(jí)過(guò)程變得非常明顯地緩慢。
為了解決這個(gè)問(wèn)題,可以把數(shù)據(jù)文件存放在一個(gè)獨(dú)立的文件夾中,可是在卸載的時(shí)候,由于這些數(shù)據(jù)文件不屬于ClickOnce的安裝目錄,也就不能自動(dòng)刪除。如果ClickOnce部署的程序在卸載的時(shí)候,能夠調(diào)用一些自定義的處理就好了。
5,又有新問(wèn)題了
有一天有個(gè)用戶(hù)搬著他的筆記本電腦來(lái)到一個(gè)窮鄉(xiāng)僻壤,這里沒(méi)有寬帶,只能用一個(gè)56K的小貓上網(wǎng)。當(dāng)他打開(kāi)軟件想工作的時(shí)候,ClickOnce提醒他,軟件有了更新的版本,你是要安裝呢還是暫時(shí)跳過(guò)?由于對(duì)56K小貓的下載速度不太有信心,他選擇了跳過(guò):反正軟件的舊版本也可以繼續(xù)使用,還是先完成工作要緊。過(guò)了幾天,這個(gè)用戶(hù)回到了寬帶社會(huì),心想現(xiàn)在可以升級(jí)版本了,可是當(dāng)他再次打開(kāi)軟件,卻沒(méi)有任何關(guān)于新版本的提示信息。
盡管我不太理解,ClickOnce就是這樣工作的:如果你選擇了【跳過(guò)】某個(gè)版本,那么你就永遠(yuǎn)【跳過(guò)】這個(gè)版本了,除非有比之更新的版本發(fā)布了,ClickOnce才會(huì)再次提醒你升級(jí)。如果是我的話(huà),我會(huì)給用戶(hù)提供【暫時(shí)跳過(guò)】和【不要再提醒我這個(gè)版本的更新】?jī)蓚€(gè)選擇,可惜微軟的技術(shù)人員似乎沒(méi)有我這樣善解人意。
這個(gè)問(wèn)題的解決辦法就是用代碼的方式調(diào)用ClickOnce的API,強(qiáng)制其再次進(jìn)行版本更新??梢詤⒖糓SDN的文章:【如何:使用 ClickOnce 部署 API 以編程方式檢查應(yīng)用程序更新】,但這種方式不太友好,更新過(guò)程中缺少一個(gè)可視化的進(jìn)度顯示,所以你可以參考MSDN的另一篇技術(shù)文章【執(zhí)行異步更新】。
盡管MSDN提供了完美的編程示例,但是真實(shí)世界往往和示例有很大差距,我準(zhǔn)備在另一篇文章里面專(zhuān)門(mén)探討一下以API方式進(jìn)行ClickOnce更新的時(shí)候會(huì)碰到的各種問(wèn)題。
6,關(guān)于證書(shū)的兩個(gè)問(wèn)題
第一,發(fā)布時(shí)候用的測(cè)試用證書(shū)有個(gè)有效期問(wèn)題,一年之后會(huì)導(dǎo)致無(wú)法繼續(xù)更新。所以我發(fā)布之前干脆把證書(shū)取消掉了,似乎也沒(méi)有問(wèn)題,用戶(hù)安裝軟件的時(shí)候會(huì)有個(gè)警告。第二,如果ClickOnce從https的地址更新,一定得保證服務(wù)器證書(shū)的有效性。如果從瀏覽器訪問(wèn)這個(gè)網(wǎng)址會(huì)彈出證書(shū)有效性的警告,ClickOnce的更新會(huì)失敗。前幾天碰到一臺(tái)客戶(hù)端PC,沒(méi)有安裝Windows的根證書(shū)(IT部門(mén)的人裝系統(tǒng)的時(shí)候自作聰明把他認(rèn)為不必要的組件都給省略了),無(wú)法驗(yàn)證服務(wù)器端證書(shū)的有效性,導(dǎo)致ClickOnce的更新不能進(jìn)行。
7,設(shè)置選項(xiàng)雖然多,但對(duì)應(yīng)實(shí)際需求的靈活性不足
ClickOnce的高級(jí)設(shè)置選項(xiàng)很多。所以當(dāng)初選擇用ClickOnce部署的時(shí)候沒(méi)考慮到其實(shí)這些選項(xiàng)的靈活性不大,很難應(yīng)付實(shí)際需求,特別是碰到對(duì)操作性 愛(ài)鉆牛角尖的用戶(hù)。
用戶(hù)最后提出來(lái)的具體要求實(shí)際上是:
1,啟動(dòng)前進(jìn)行更新;
2,網(wǎng)速過(guò)慢,更新過(guò)程過(guò)于耗費(fèi)時(shí)間的時(shí)候,在途中可以隨時(shí)取消掉,使用老版本啟動(dòng);
3,用戶(hù)工作完畢,軟件關(guān)閉的時(shí)候,把剛才取消掉的更新重新執(zhí)行一次。因?yàn)檫@時(shí)候不著急工作了,可以慢慢下載
單純使用ClickOnce的選項(xiàng)設(shè)置根本無(wú)法實(shí)現(xiàn)這樣的需求,而全部拋棄ClickOnce也為時(shí)已晚,最后只好取消掉選項(xiàng)設(shè)置里的自動(dòng)更新,完全采用編碼方式調(diào)用API的方式進(jìn)行更新。過(guò)程中雖然遇到各種各樣的小問(wèn)題,好在最后基本實(shí)現(xiàn)了用戶(hù)的要求。
不過(guò)這也是微軟產(chǎn)品的特性:使用方便,看似強(qiáng)大...不靈活
--------------------------------------------------------------------------------------
本文所描述的問(wèn)題,都基于VisualStudio2008 SP1,.NET Framework3.5 SP1的開(kāi)發(fā)環(huán)境。
也許在最新版本的VisualStudio2010中,有些問(wèn)題可能已經(jīng)得到改善,我還沒(méi)有研究過(guò),另外有些問(wèn)題可能只是我的誤解,歡迎大家指正!
--------------------------------------------------------------------------------------
關(guān)于ClickOnce技術(shù)的簡(jiǎn)單介紹,可以參照互動(dòng)百科:
http://www.hudong.com/wiki/CLICKONCE
--------------------------------------------------------------------------------------
聯(lián)系客服