應用程式更新的方法一般有兩種:一是通知使用者(例如發E-mail),讓使用者到指定的網站地址下載更新的程式;二是將更新的職責從使用者那邊轉移到應用程式自身,由應用程式本身取代使用者取得並安裝軟體的更新,客戶端應用程式本身負責從一個已知伺服器下載並安裝更新,使用者唯一需要介入的是決定是否願意現在或以後安裝新的更新。顯然,後者比前者更友善。現在你可以看到類似後者方法的實際產品,像是Windows XP和Microsoft Money。本文所介紹的.NET應用程式更新元件就可以提供類似的功能。
一、.NET應用程式更新元件介紹
.NET 應用程式更新元件AppUpdater 是使用.NET框架開發的。儘管AppUpdater 不是微軟的產品,但是只要你在VS.NET工具列中添加了該組件,就可以像使用其它組件一樣通過拖曳的方式將該組件從工具列中拖放到你的應用程序中,並且設定一些屬性(例如取得更新的位置、頻率等)之後就可以使得你的客戶端應用程式具備自動更新的功能。
二、工作原理
要深入理解.NET客戶端應用程式更新元件的工作原理,需要仔細研究實現客戶端應用程式更新有那些必須要做的事情。第一步需要做的是檢查是否有更新;當發現有更新時,開始第二步工作-下載更新;當更新下載完成時,進行是最後一步的工作-實現更新。
(一) 為更新做檢查
作為開發者,首先你得告訴應用程式到什麼地方去做更新檢查,否則它豈不是要大海撈針?其次,確定何時做更新檢查。不可能用戶每次一運行客戶端程序,而它就在後台不停的進行更新檢查,那多浪費資源!最後還有一項重要的事情要解決,那就是如何進行更新檢查。 .NET應用程式更新元件使用HTTP進行通訊,這允許客戶端應用程式穿透防火牆來進行更新。並且進行更新檢查所需的位址就成了已知的Web伺服器的一個URL位址,第一個問題順利解決。
.NET應用程式更新元件在元件產生的基礎上產生一個線程,該線程負責進行更新檢查。該執行緒在大多數時間處於休眠狀態,但會在設定好的間隔甦醒並實現一次更新檢查。應用程式為新的更新所做的檢查的頻率依賴於各應用自身。進行更新檢查的間隔常用值的範圍一般是從一個小時到幾天。這種輪詢的基本方法並不適合所有情況。例如Microsoft Money只是在使用者讓它去進行更新檢查時它才去檢查。在這種情況下,更新輪詢線程可被停用。
透過以指令呼叫更新元件的CheckForUpdate()方法來實作更新檢查。
關於如何進行更新檢查的方法有幾種:
方法一:直接檔案檢查-使用HTTP來比較伺服器和用戶端應用程式的最後的修改日期/時間戳記是否一致。如果伺服器上有更新的文件,客戶端就知道可以更新自己了。對於網頁瀏覽器來講,也是同樣的道理,它知道是否需要重新下載一個html頁面或圖片或是否可以重複使用先前已下載的。當應用程式有一個新的版本可用時,管理員簡單地拷貝一個更新的版本來覆蓋Web伺服器上的舊版本。這種方法的問題在於更新不是自動進行,由此會出現潛在的失敗可能。例如,如果管理員正在更新Web伺服器上的應用程式版本,同時有個客戶正在下載更新之前的版本,那麼這個客戶的電腦上就會既存在更新之前的一些文件,也存在更新之後新版本的某些文件。基於上述原因,對於重要的應用程式不提倡使用直接文件檢查來更新。
方法二:明確檢查-在伺服器上使用一個明確的設定檔。一個可和.NET應用程式更新元件使用的有效伺服器明確檔大致是這個樣子:..
<VersionConfig>
<AvailableVersion>1.0.0.0</AvailableVersion>
<ApplicationUrl> http://localhost/demos/selfupdate/V1/ </
ApplicationUrl>
</VersionConfig>
AvailableVersion指定最新的可用組件的版本號碼。 ApplicationURL屬性指定該版本應用程式所在的URL位址。當管理員想要更新客戶端應用程式時,他們就會將應用程式的新版本拷貝到網路伺服器上並且適當地修改伺服器明確文件。客戶端本身會偵測到伺服器明確檔已被修改,然後下載明確檔。用戶端隨後比較顯式檔案中指定的組件版本號與應用程式EXE檔案的版本號。如果伺服器顯式檔案中的可用版本號較新,應用程式就知道需要更新了。這種方法對大多數應用程式而言是推薦使用的方法。
方法三:XML Web Service 檢查-XML WebServices提供一種更進階的更新檢查方式。例如,假定你希望在進行更新你的其他使用者之前先對一系列早期使用者進行更新,如果客戶端應用程式呼叫一個XML WebService來檢查一項更新是否可用,那個XML Web Service還可以在資料庫中查詢該使用者並判斷該使用者是否為早期使用者。如果他們是早期用戶,XML Web Service就傳回一個值表示更新可用。如果不是,Web Service就回傳一個值表示更新不可用。但本文介紹的.NET應用程式更新元件並不提供直接的XML Web Service支援。
若要採用XML Web Service來進行更新檢查,先建立XML Web Service並掛鉤一個OnCheckForUpdate事件。這樣就允許你自己的自訂檢查代替輪詢者線程更新檢查。 OnCheckForUpdate事件有一個回傳值,表示更新是否被偵測到。
(二) 下載更新
當.NET應用程式更新元件偵測到一項新的更新可用時它會自動啟動另一個執行緒並開始非同步後台下載更新。
下載使用HTTP-DAV來完成。 DAV 是一種擴充的HTTP,.. 它提供諸如目錄和檔案枚舉這樣的功能。一個完整的下載過程始於指定一個URL。採用URL來下載依賴完成更新檢查所使用的方式。例如,如果使用伺服器明確文件,下載更新所使用的URL透過在伺服器明確文件中的ApplicationURL屬性指定。
更新下載顯然需要一定的健壯性。在下載和更新之後讓客戶端應用程式處於任何不穩定的狀態是不可接受的。下載過程中任何問題可能都會出現:更新檔案所屬的Web 伺服器可能會宕機,客戶端機器可能會崩潰,或者因為某種原因用戶只是簡單的關閉了應用程式。由於應用程式正在進行下載,如果它被關閉的話,下載將會停止。一種可選的設計方案是使用單獨的系統服務來進行應用程式的下載和更新。使用系統服務,即便應用程式本身沒有在運行,更新下載也會繼續。實際上,Windows XP就有一種稱為BITS的內建的下載服務,其目的就在此。 BITS是Windows XP用來對Windows本身進行下載更新的。想查看更多關於BITS的信息,請參閱http://msdn.microsoft.com/library/en-us/dnwxp/html/WinXP_BITS.asp 。在.NET應用程式更新元件中沒有使用這種服務,因此它可以在不支援系統服務的Windows 9x中使用。
(三) 實作更新
.NET應用程式更新元件透過將下載和更新過程分為單獨的兩個階段來獲得健全性。當每一階段都完成時,請在位於客戶端應用程式目錄下的更新明確檔案(manifest file)中記載。如果下載或更新任何一個階段中的過程被打斷,它就會在下一次應用程式啟動時從上一次完成的斷點繼續原來的工作。每個階段都可以重新運行,因此如果在一個階段中間出現失敗,重新運行該階段就可以成功。如果有錯誤發生,例如在下載過程中與伺服器的連結遺失,.NET更新元件會在稍後重試。如果報告了非常多的錯誤(例如web伺服器再也沒有回到線上狀態),下載和更新將會被放棄並且報告錯誤。
我們的第一個方法是簡單地啟動一個單獨的進程來實現更新。這個單獨的進程將會先關閉應用程式進程,實現更新(因為這時候已解鎖),重啟應用程式進程並且在完成之後關閉自己。因此,這種設計有三個基本的問題:
. 在某些情況下它不起作用。在更新應用程式時,更新進程關閉原始的應用程式進程,更新進程本身也要關閉,因此也不會實現更新。
. 我們希望能夠自動更新所有要實現更新的程式碼。我們希望自動安裝修補的能力不僅發生在應用程式上,而且.NET應用程式更新元件本身也可以。使用這種模式,我們不能更新實作更新的進程。
. 強制使用者關閉應用程式並在使用過程中等待,這是很不禮貌的。
用來實現應用程式更新的最後一種方法是使用.NET框架並行程序集模式。作為試圖更新應用程式本身的替代方案,產生一個比目前存在版本新的應用程式版本。
新版本可以透過合併目前現存的應用程式目錄與下載的更新版本來產生。當新版本完成時,使用者下次重新開啟應用程式時會自動使用新版本。原始應用程式的拷貝就可以被移除了。棘手問題是弄清楚在某個指定時刻哪個版本該被載入。我們介紹一個名稱為Appstart的應用程式。 Appstart是進入你應用程式的入口點,使用這個模式,你的應用程式目錄看起來像這樣:..
--> Program Files
--> MyApp
--> Appstart.exe
--> Appstart.config
- -> V1 Folder
--> MyApp.exe
--> V1.1 Folder
--> MyApp.exe
要運行你的應用程序,你通常是啟動Appstart.exe。如果你想在桌面上有個快捷鍵,那個快捷鍵必須應該指向Appstart而不是直接指向應用程式(注意,你可以重命名AppStart.exe 為任何你想要的名字,例如YourApp.exe)Appstart.exe是個非常簡單的程序,它讀取Appstart.config檔案並且載入指定的應用程式。一個有效Appstart.config檔如下所示:
<Config>
<AppFolderName>V1 Folder</AppFolderName>
<AppExeName>MyApp.exe</AppExeName>
<AppLaunchMode>appdomain</AppLaunchMode>
</Config>
AppFolderName指定包含目前要執行的應用程式版本的子資料夾。 AppExeName包含在那個資料夾下要載入的exe檔名。當一個應用程式更新完成時,最後一步就是修改AppFolderName的值為指向應用程式的新版本。這樣,下次用戶執行應用程式時,就會執行新的應用程式更新後的版本。 AppLaunchMode指定如何載入應用程式。有兩種方式載入應用程式:第一種方式是使用AppDomains。 AppDomains是.NET框架公用語言執行時期的特性,也是獨立的邏輯單元和管理物件。公用語言運行時允許每個進程中存在多個應用程式域。這樣Appstart.exe就能夠在單獨的AppDomain中同時卻是相同的AppStart.exe進程中載入你的應用程式。儘管事實是兩個不同的exe 程式在運行(即Appstart.exe和MyApp.exe),但只有一個進程在使用。對於大多數應用程式AppDomains會運作得很好,當然,在一個單獨的AppDomain中運行和在一個單獨的進程中運行還是有些細微差別的。在這種情況下,AppLaunchMode可以設定為“process”,這會使應用程式在單獨進程中載入。
一旦Appstart啟動應用程序,它就會進入休眠狀態等待應用程式終止。一旦應用程式終止,Appstart也會關閉。
三、實例演練
前面我們討論了.NET應用程式更新是如何運作的,現在我們來將它應用在實例中。
第一步:建立應用程式來進行更新
1. 使用VS.NET產生一個新的Windows應用項目,命名為"SampleApp"。
2. 給窗體一個你選擇的有趣的背景色。我們將使用背景色來與後面更新的版本區別。
3. 現在讓我們為這個應用程式增加一個細微的功能,首先為你的窗體增加一個按鈕。壓縮檔案中包含一個擁有簡單Windows窗體的組件。將壓縮檔案中SamplesSampleAppSimpleForm 組件增加一個參考。然後在你的按鈕事件句柄中加入兩行程式碼:
..
SimpleForm.Form1 F = new SimpleForm.Form1();
F.Show();
4. 將你的build標誌從debug轉換成RELEASE。這將允許我們避免稍後當我們產生一個應用程式的新版本而同時原始拷貝正在運行產生的pdb檔案鎖定問題。產生並測試你的應用程式。
第二步:新增.NET應用程式更新元件
1. 在VS.NET工具列的元件標籤上,右鍵選擇「自訂工具列」。選擇“.NET框架組件”標籤。點「瀏覽」並選擇位於壓縮檔中AppUpdater 項目下的AppUpdater.dll,點選OK。
2. 一個AppUpdater圖示現在應該出現在工具列的元件清單的底部。將AppUpdater 元件拖曳到SampleApp窗體上。一個名為appUpdater1的.NET應用程式更新元件的實例會出現在表單的底部。
第三步:設定.NET
應用程式更新元件在這一步驟我們將設定.NET應用程式更新元件。注意這個範例你只需改變最開始的四個屬性,其它的採用預設值。
AppUpdater屬性:這是.NET Application應用程式更新的核心,對於本程式需要做以下設定:
(1)AutoFileLoad:這個控制後面要描述的命令下載特徵,現在將它設為true。
(2)ChangeDetectionMode:此枚舉決定如何為更新進行檢查。在該例中,我們將使用一個伺服器明確檢查,因此將這個值設為「ServerManifestCheck 」。
(3)ShowDefaultUI: .NET 應用程式更新元件具有一系列使用者介面來通知使用者一些事件,例如有一個新的更新可以使用了或在更新期間發生錯誤等。這種使用者介面可以透過設定預設的使用者介面為無效而用自訂應用程式指定的使用者介面來取代它,掛鉤適當的事件(例如
OnUpdateComplete)並彈出自訂使用者介面。對於該例我們將使用預設的使用者介面,因此將這個值設為true 。
(4)UpdateUrl :UpdateUrl 是決定更新程式到何處去尋找更新的。在該例中我們使用一個伺服器明確檔來檢查更新,因此這個屬性應設定為伺服器明確檔的URL 。
在該範例中將它設為: http://yourWebserver/SampleApp_ServerSetup/UpdateVersion.xml 。請用你的Web 伺服器名稱來取代「yourWebserver 」。
Downloader 屬性:AppUpdater 元件有兩個子元件。第一個稱之為Downloader,它控制元件的下載和Poller屬性:AppUpdater的第二個子元件是Poller,Poller控制更新檢查。
(1)AutoStart:布林值,在應用程式啟動時控制Poller 是否應開始輪詢或它是否應等待直到有計劃的更新查詢開始。
(2)DownloadOnDetection:布林值,控制Poller 在一個新的更新發現時是否立即開始下載更新,或者是否透過呼叫DownloadUdpate() 方法開始明確下載。
(3)InitialPollInterval:應用程式啟動後在第一次執行更新檢查前等待的秒數。
(4)PollInterval:第一次更新檢查之後,PollInterval 控制後續每次更新檢查之間間隔的秒數,注意:預設為每30 秒進行一次檢查;顯然,你會希望你的應用程式減少更新檢查的頻率。
所有這一切完成之後,你的屬性表格看起來應該是下面這個樣子:
SamplesSampleAppSampleApp_Complete目錄包含一個應用程式正確安裝的版本。
安裝:
(1)DownloadRetryAttempts:在下載期間如果有錯誤發生(例如Web 伺服器宕機)downloader 會稍後重試。這個屬性控制downloader 認為是徹底的應用程式更新錯誤之前重試網路請求的次數。
(2)SecondsBeteweenDownloadRety:重試網路請求之前等待的秒數。
(3)UpdateRetryAttempts: 在更新期間如果發生嚴重錯誤,(例如downloader 超過了試圖重試的次數),就會產生一個應用程式更新錯誤。預設的,將會停止試圖更新。但是在應用程式下一次啟動時會試圖恢復(例如更新Web 伺服器可能會宕機好幾天)。這個屬性控制試圖更新的次數。如果超過這個值,updater 就會取消更新,重置它的狀態並傳回更新檢查。
(4)ValidateAssemblies: 這個屬性控制下載組件有效完成的等級。更多資訊請參閱這篇文章的安全一節。
第四步:產生並在客戶端部署應用程式V1版本。
在SampleApp專案中,開啟AssemblyInfo.cs檔案。將AssemblyVersion的值從「1.0」修改為「1.0.0.0」。這會引起在產生組件時獲得值為「1.0.0.0」.. 的標記,該標記取代VS.NET通常指定為遞增的值。
1. 生成應用程式。
2.從壓縮檔案將SamplesSampleAppSampleApp_ClientSetup目錄拷貝到你的本機上。要注意此目錄已經包含了AppStart.exe。 AppStart.config已經設定為指向1.0.0.0目錄並且啟動SampleApp.exe。
從SampleApp的release目錄下拷貝SampleApp(Appupdater.dll,SimpleForm.dll和SampleApp.exe)
到客戶端SampleApp_ClientSetup1.0.0.0目錄下。至此,一個功能完整的應用程式版本已被「安裝」到了客戶端,可以透過執行AppStart.exe來執行。
第五步:安裝Web伺服器
在這一步驟我們將安裝Web伺服器以提供更新輪詢功能。 .NET應用程式更新元件使用HTTP-DAV來下載應用程式更新,因此需要一個支援HTTP-DAV的網路伺服器。 Windows 2000上的IIS5.0和更新的作業系統都支援HTTP-DAV。
1.將Samples/SampleApp_ServerSetup目錄拷貝到你的Web伺服器上的wwwroot目錄下。
2. 將SampleApp的V1版本拷貝到Web伺服器的1.0.0.0資料夾。
3. 在Web伺服器上為SampleApp_ServerSetup目錄啟用IIS的「目錄瀏覽」權限。
第六步:自動更新應用程式
OK,.. 現在是時間來透過自動安裝新版本來看看以上這些艱苦工作的結果了。
1. 如果你部署在客戶端的SampleApp版本沒有運行,載入它讓它運行,記得使用AppStart.exe。
2. 回到VS.NET並在SampleApp視窗中做一些可以被注意到的修改(例如修改背景色)。
3. 將AssemblyInfo.cs的版本資訊改為2.0.0.0。
4. 重新生成。
5. 回到Web伺服器並產生一個和1.0.0.0目錄同等的目錄2.0.0.0。從release生成目錄下將新版本應用程式拷貝到Web伺服器上新建的2.0.0.0目錄下。
6.開啟UpdateVersion.xml 並修改AvailableVersion為2.0.0.0。修改ApplicationURL為指向新的2.0.0.0路徑。
7. 儲存對UpdateVersion.xml所做的修改。
一旦你儲存了新的UpdateVersion.xml,在30秒之內,執行中的SampleApp拷貝將會偵測到新的可用版本。
四、按需安裝、安全、可擴充性及調試
(一)依需求安裝
所謂依需求安裝,指只有主可執行程式被明確安裝到客戶機上。應用程式剩餘的部分可以根據基本需要自動下載和安裝。
透過.NET應用程式更新元件的AutoFileLoad屬性來啟動依需求安裝。你必須仔細考慮在你的應用程式中程序集邊界所處的位置以及什麼動作會引起程序集被下載。由於組件的下載涉及網路輸入輸出,因此下載所花費的時間是可變的。在程式集下載期間,應用程式會被凍結等待程式集下載完成。
(二)部署安全
自動安裝應用程式更新的能力具備許多好處,但它也伴隨著一些潛在的危險。當你讓安裝更新變得簡單時,如果不小心,你也可能讓安裝惡意程式碼變得簡單。有兩種危險,第一種危險是有人會用自己的Web伺服器欺騙用來部署更新的Web伺服器。他們可能會利用那台網路伺服器在你的應用程式路徑安裝一個病毒程式。阻止欺騙或其它透過網路進行的不正當幹預的最簡單的方法是使用HTTPS。要和.NET應用程式更新元件一起使用HTTPS,可以簡單地用HTTPS URLs來取代HTTP URLs。當然,HTTPS 不是銀彈。使用HTTPS有兩個問題,第一是可擴展性。使用HTTPS需要伺服器加密所有從網路伺服器下載的檔案。如果一個應用程式的更新檔案很大,加密更新檔案的代價會使伺服器的負擔過重。使用HTTPS的另一個問題是它對第二種安全危險毫無益處。第二種危險是駭客既可能從內部也可能從外部來攻擊你的伺服器。一旦攻擊成功,則有可能意味著成百上千的客戶端也透過自動更新遭受連累,這種情況將是災難性的。
為解決這個問題,.NET應用程式更新元件使用為.NET組件新增強名稱的特性來驗證所下載的組件。如果.NET應用程式更新元件偵測到下載期間一個組件不是使用你的金鑰簽署的,下載就會取消。這意味著只有擁有你的應用程式私鑰的人才能夠建立可自動部署的更新檔案。
要驗證組件有效,.NET應用程式更新元件驗證你目前安裝的應用程式可執行程式的公鑰和下載的更新的公鑰是否匹配。如果兩個程式集以相同且保密的私鑰簽名,那麼嵌入的公鑰也就相同。因為被CLR載入的組件為了驗證它的公鑰,CLR計算它正常的雜湊值檢查來保證程序集實際上是真正的組件而不是被做了手腳的組件。為了能夠在下載時驗證,可以為你所有的應用程式集添加強名稱並將.NET應用程式更新元件的ValidateAssemblies屬性設為true。
在下載時進行組件驗證會起很大的作用,但實際上,應用程式會經常有不同私鑰簽署的元件。例如,你的應用程式可能有兩個檔案:使用你的私鑰簽署的可執行組件和另一個包含你購買的應用在你的應用程式中的第三方圖表控制項的dll程式集。第三方程式集可能使用第三方而不是你自己的私鑰來簽署。使情況變得更為複雜的是,在你的應用程式中用來簽署組件的有效私鑰的設定會隨著版本號的改變可能會改變。你該如何自動更新那些應用程式的類型?要解決這個問題,你可以在你的應用程式中產生一個包含有效公鑰的清單的組件。將該組件使用應用程式的主私鑰(應用程式的exe檔案簽署的金鑰)簽署並把該組件放到Web伺服器上和應用程式更新檔案一起的目錄下。在更新下載程序開始之前,.NET應用程式更新元件將會檢查Web伺服器上應用程式更新目錄下一個名為"AppUpdaterKeys.dll"的組件。如果存在,該組件就會被下載。該程序集會被拿來和主應用程式的公鑰對比驗證。如果簽章有效,金鑰清單會被提取出來。從此之後,任何處於該清單中的金鑰都會被認為是更新檔案的有效簽章。
有關安全性方面建議的方法是使用HTTPS URLs來實現更新檢查。這會提供第一個等級的欺騙保護。對於更新下載,最好不要使用HTTPS RLs以避免使你Web伺服器的負荷過重。而是為你的應用程式的程式集添加強名稱並使用程式集驗證特性。
(三)可擴展性
在這篇文章前面講過的範例中我們簡單地透過拖放一個元件到應用程式中並設定一些屬性來實現自動部署。
雖然這在許多應用程式中運作的很好,但在某些應用程式中會需要高階的控制,這只能透過寫入程式碼來獲得。我們可以寫自己的程式碼來取代掉.NET應用程式更新元件標準流程,使用重寫的CheckForUpdate()和ApplyUpdate()方法來客製化檢查和更新行為。
(四)調試
這一節將指出一些首選的調試選項,以及描述使用該組件的用戶大多數常見的問題。
.NET應用程式更新器在相同和AppStart.exe的目錄下產生一個名為AppUpdate.log的隱藏日誌檔案。
所有的更新成功和失敗訊息都記錄在該日誌中。當有一個特殊的客戶端不能成功更新時日誌檔案會特別有用。
你可以使用日誌來判斷在什麼時間以及是如何更新失敗的。另外,.NET應用程式更新元件使用.NET框架的Debug類別來輸出大量有用的信息。如果你在調試器中運行你的應用程序,你會在輸出視窗中看到這些資訊。你可以循著.NET應用程式更新器的記錄重點觀察並找到出問題的地方。
如果由於某種原因,你無法使得.NET應用程式更新器工作,在你深入調試之前請確定以下幾點,你遇到的問題很可能就是如下之一:..
. 你是否將IIS目錄瀏覽給打開了?如果沒有,更新器將不會下載安裝任何檔案。
. 你是否正確的部署了一切並正確設定了URL?
. 如果你的應用程式安裝在program files目錄下,確定你是該機的超級管理員或超級使用者嗎?如果不是,你將不會有寫入權限來更新應用程式。
. 你是在應用程式的主用戶介面執行緒中產生AppUpdater物件的嗎?如果不是,更新器將不能顯示使用者介面並且在激發事件回到使用者介面時失敗。
. 是否更新成功,但應用程式使用新的更新自動重啟時失敗? .NET 應用程式更新元件試圖透過呼叫Application.Exit方法來退出應用程式。然而,該方法並不能保證關閉一個應用程式。如果你產生並遺留了單獨的執行緒在運行,該方法就無法關閉進程。確保所有執行緒終止的解決的方案是透過呼叫Application.OnExit事件,或掛鉤.NET應用程式更新器的OnUpdateComplete事件並自行處理關閉。
五、總結
客戶端應用程式部署方便是.NET框架第一個版本的重要的目標。用.NET框架建立解決部署問題的客戶端應用程式是一種很好的技術。部署方便仍然是未來.NET框架新版本的重要目標。就方案而言,這裡描述的.NET應用程式更新元件代表了我們的一些想法,在未來版本的.NET框架中我們將可以直接使用。然而,在那個時候到來之前的這段期間,.NET應用程式更新元件不失為開始建立自動更新應用程式的一種重要的方法
出自:csdn,在天極上看到的,還沒仔細研究,留做以後參考