c# 智能升级程序代码
最近單位開發(fā)一個(gè)項(xiàng)目,其中需要用到自動(dòng)升級(jí)功能。因?yàn)樽詣?dòng)升級(jí)是一個(gè)比較常用的功能,可能會(huì)在很多程序中用到,于是,我就想寫一個(gè)自動(dòng)升級(jí)的組件,在應(yīng)用程序中,只需要引用這個(gè)自動(dòng)升級(jí)組件,并添加少量代碼,即可實(shí)現(xiàn)自動(dòng)升級(jí)功能。因?yàn)槲覀兊某绦蛑锌赡馨鄠€(gè)exe或者dll文件,所以要支持多文件的更新。
首先,要確定程序應(yīng)該去哪里下載需要升級(jí)的文件。我選擇了到指定的網(wǎng)站上去下載,這樣比較簡(jiǎn)單,也通用一些。在這個(gè)網(wǎng)站上,需要放置一個(gè)當(dāng)前描述最新文件列表的文件,我們估且叫它服務(wù)器配置文件。這個(gè)文件保存了當(dāng)前最新文件的版本號(hào)(lastver),大小(size),下載地址(url),本地文件的保存路徑(path),還有當(dāng)更新了這個(gè)文件后,程序是否需要重新啟動(dòng)(needRestart)。這個(gè)文件大致如下:
updateservice.xml
<?xml version="1.0" encoding="utf-8"?>
<updateFiles>
? <file path="AutoUpdater.dll"? url="http://update.iyond.com/CompanyClientApplication/AutoUpdater.zip" lastver="1.0.0.0" size="28672" needRestart="true" />
? <file path="CompanyClient.exe"? url="http://update.iyond.com/CompanyClientApplication/CompanyClient.zip" lastver="1.1.0.0" size="888832 " needRestart="true" />
? <file path="HappyFenClient.dll"? url="http://update.iyond.com/CompanyClientApplication/HappyFenClient.zip" lastver="1.0.0.0" size="24576" needRestart="true" />
? <file path="NetworkProvider.dll"? url="http://update.iyond.com/CompanyClientApplication/NetworkProvider.zip" lastver="1.0.0.0" size="32768" needRestart="true" />
? <file path="Utility.dll"? url="http://update.iyond.com/CompanyClientApplication/Utility.zip" lastver="1.0.0.0" size="20480" needRestart="true" />
? <file path="Wizard.dll"? url="http://update.iyond.com/CompanyClientApplication/Wizard.zip" lastver="1.0.0.0" size="24576"? needRestart="true" />
</updateFiles>
同時(shí),客戶端也保存了一個(gè)需要升級(jí)的本地文件的列表,形式和服務(wù)器配置文件差不多,我們叫它本地配置文件。其中,<Enable>節(jié)點(diǎn)表示是否啟用自動(dòng)升級(jí)功能,<ServerUrl>表示服務(wù)器配置文件的地址。
update.config
<?xml version="1.0" encoding="utf-8"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
? <Enabled>true</Enabled>
? <ServerUrl>http://update.iyond.com/updateservice.xml</ServerUrl>
? <UpdateFileList>
??? <LocalFile path="AutoUpdater.dll" lastver="1.0.0.0" size="28672" />
??? <LocalFile path="CompanyClient.exe" lastver="1.1.0.0" size="888832 " />
??? <LocalFile path="HappyFenClient.dll" lastver="1.0.0.0" size="24576" />
??? <LocalFile path="NetworkProvider.dll" lastver="1.0.0.0" size="32768" />
??? <LocalFile path="Utility.dll" lastver="1.0.0.0" size="20480" />
??? <LocalFile path="Wizard.dll" lastver="1.0.0.0" size="24576"? />
? </UpdateFileList>
</Config>
使用自動(dòng)各級(jí)組件的程序在啟動(dòng)時(shí),會(huì)去檢查這個(gè)配置文件。如果發(fā)現(xiàn)有配置文件中的文件版本和本地配置文件中描述的文件版本不一致,則提示用戶下載。同時(shí),如果本地配置文件中某些文件在服務(wù)器配置文件的文件列表中不存在,則說(shuō)明這個(gè)文件已經(jīng)不需要了,需要?jiǎng)h除。最后,當(dāng)升級(jí)完成后,會(huì)更新本地配置文件。
我們先來(lái)看一下如何使用這個(gè)組件。
在程序的Program.cs的Main函數(shù)中:
[STAThread]
static void Main()
{
??? Application.EnableVisualStyles();
??? Application.SetCompatibleTextRenderingDefault(false);
??? AutoUpdater au = new AutoUpdater();
??? try
??? {
??????? au.Update();
??? }
??? catch (WebException exp)
??? {
??????? MessageBox.Show(String.Format("無(wú)法找到指定資源\n\n{0}", exp.Message), "自動(dòng)升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
??? }
??? catch (XmlException exp)
??? {
??????? MessageBox.Show(String.Format("下載的升級(jí)文件有錯(cuò)誤\n\n{0}", exp.Message), "自動(dòng)升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
??? }
??? catch (NotSupportedException exp)
??? {
??????? MessageBox.Show(String.Format("升級(jí)地址配置錯(cuò)誤\n\n{0}", exp.Message), "自動(dòng)升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
??? }
??? catch (ArgumentException exp)
??? {
??????? MessageBox.Show(String.Format("下載的升級(jí)文件有錯(cuò)誤\n\n{0}", exp.Message), "自動(dòng)升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
??? }
??? catch (Exception exp)
??? {
??????? MessageBox.Show(String.Format("升級(jí)過(guò)程中發(fā)生錯(cuò)誤\n\n{0}", exp.Message), "自動(dòng)升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
??? }
??? Application.Run(new MainUI());
}
如上所示,只需要簡(jiǎn)單的幾行代碼,就可以實(shí)現(xiàn)自動(dòng)升級(jí)功能了。
軟件運(yùn)行截圖:
下面,我們來(lái)詳細(xì)說(shuō)一下這個(gè)自動(dòng)升級(jí)組件的實(shí)現(xiàn)。
先看一下類圖:
AutoUpdater:自動(dòng)升級(jí)的管理類,負(fù)責(zé)整體的自動(dòng)升級(jí)功能的實(shí)現(xiàn)。
Config:配置類,負(fù)責(zé)管理本地配置文件。
DownloadConfirm:一個(gè)對(duì)話框,向用戶顯示需要升級(jí)的文件的列表,并允許用戶選擇是否馬上升級(jí)。
DownloadFileInfo:要下載的文件的信息
DownloadProgress:一個(gè)對(duì)話框,顯示下載進(jìn)度。
DownloadProgress.ExitCallBack,
DownloadProgress.SetProcessBarCallBack,
DownloadProgress.ShowCurrentDownloadFileNameCallBack:由于.NET2.0不允許在一個(gè)線程中訪問另一個(gè)線程的對(duì)象,所以需要通過(guò)委托來(lái)實(shí)現(xiàn)。
LocalFile:表示本地配置文件中的一個(gè)文件
RemoteFile:表示服務(wù)器配置文件中的一個(gè)文件。
UpdateFileList:一個(gè)集合,從List<LocalFile>繼承
我們先整體看一下AutoUpdater.cs:
public class AutoUpdater
{
??? const string FILENAME = "update.config";
??? private Config config = null;
??? private bool bNeedRestart = false;
??? public AutoUpdater()
??? {
??????? config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
??? }
??? /**/
??? /// <summary>
??? /// 檢查新版本
??? /// </summary>
??? /// <exception cref="System.Net.WebException">無(wú)法找到指定資源</exception>
??? /// <exception cref="System.NotSupportException">升級(jí)地址配置錯(cuò)誤</exception>
??? /// <exception cref="System.Xml.XmlException">下載的升級(jí)文件有錯(cuò)誤</exception>
??? /// <exception cref="System.ArgumentException">下載的升級(jí)文件有錯(cuò)誤</exception>
??? /// <exception cref="System.Excpetion">未知錯(cuò)誤</exception>
??? /// <returns></returns>
??? public void Update()
??? {
??????? if (!config.Enabled)
??????????? return;
??????? /**/
??????? /*
???? * 請(qǐng)求Web服務(wù)器,得到當(dāng)前最新版本的文件列表,格式同本地的FileList.xml。
???? * 與本地的FileList.xml比較,找到不同版本的文件
???? * 生成一個(gè)更新文件列表,開始DownloadProgress
???? * <UpdateFile>
???? * <File path="" url="" lastver="" size=""></File>
???? * </UpdateFile>
???? * path為相對(duì)于應(yīng)用程序根目錄的相對(duì)目錄位置,包括文件名
???? */
??????? WebClient client = new WebClient();
??????? string strXml = client.DownloadString(config.ServerUrl);
??????? Dictionary<string, RemoteFile> listRemotFile = ParseRemoteXml(strXml);
??????? List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>();
??????? //某些文件不再需要了,刪除
??????? List<LocalFile> preDeleteFile = new List<LocalFile>();
??????? foreach (LocalFile file in config.UpdateFileList)
??????? {
??????????? if (listRemotFile.ContainsKey(file.Path))
??????????? {
??????????????? RemoteFile rf = listRemotFile[file.Path];
??????????????? if (rf.LastVer != file.LastVer)
??????????????? {
??????????????????? downloadList.Add(new DownloadFileInfo(rf.Url, file.Path, rf.LastVer, rf.Size));
??????????????????? file.LastVer = rf.LastVer;
??????????????????? file.Size = rf.Size;
??????????????????? if (rf.NeedRestart)
??????????????????????? bNeedRestart = true;
??????????????? }
??????????????? listRemotFile.Remove(file.Path);
??????????? }
??????????? else
??????????? {
??????????????? preDeleteFile.Add(file);
??????????? }
??????? }
??????? foreach (RemoteFile file in listRemotFile.Values)
??????? {
??????????? downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size));
??????????? config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size));
??????????? if (file.NeedRestart)
??????????????? bNeedRestart = true;
??????? }
??????? if (downloadList.Count > 0)
??????? {
??????????? DownloadConfirm dc = new DownloadConfirm(downloadList);
??????????? if (this.OnShow != null)
??????????????? this.OnShow();
??????????? if (DialogResult.OK == dc.ShowDialog())
??????????? {
??????????????? foreach (LocalFile file in preDeleteFile)
??????????????? {
??????????????????? string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.Path);
??????????????????? if (File.Exists(filePath))
??????????????????????? File.Delete(filePath);
??????????????????? config.UpdateFileList.Remove(file);
??????????????? }
??????????????? StartDownload(downloadList);
??????????? }
??????? }
??? }
??? private void StartDownload(List<DownloadFileInfo> downloadList)
??? {
??????? DownloadProgress dp = new DownloadProgress(downloadList);
??????? if (dp.ShowDialog() == DialogResult.OK)
??????? {
??????????? //更新成功
??????????? config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
??????????? if (bNeedRestart)
??????????? {
??????????????? MessageBox.Show("程序需要重新啟動(dòng)才能應(yīng)用更新,請(qǐng)點(diǎn)擊確定重新啟動(dòng)程序。", "自動(dòng)更新", MessageBoxButtons.OK, MessageBoxIcon.Information);
??????????????? Process.Start(Application.ExecutablePath);
??????????????? Environment.Exit(0);
??????????? }
??????? }
??? }
??? private Dictionary<string, RemoteFile> ParseRemoteXml(string xml)
??? {
??????? XmlDocument document = new XmlDocument();
??????? document.LoadXml(xml);
??????? Dictionary<string, RemoteFile> list = new Dictionary<string, RemoteFile>();
??????? foreach (XmlNode node in document.DocumentElement.ChildNodes)
??????? {
??????????? list.Add(node.Attributes["path"].Value, new RemoteFile(node));
??????? }
??????? return list;
??? }
??? public event ShowHandler OnShow;
}
在構(gòu)造函數(shù)中,我們先要加載配置文件:
public AutoUpdater()
{
??? config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
}
最主要的就是Update()這個(gè)函數(shù)了。當(dāng)程序調(diào)用au.Update時(shí),首先檢查當(dāng)前是否開戶了自動(dòng)更新:
if (!config.Enabled)
??? return;
如果啟用了自動(dòng)更新,就需要去下載服務(wù)器配置文件了:
WebClient client = new WebClient();
string strXml = client.DownloadString(config.ServerUrl);
然后,解析服務(wù)器配置文件到一個(gè)Dictionary中:
Dictionary<string, RemoteFile> listRemotFile = ParseRemoteXml(strXml);
接下來(lái)比較服務(wù)器配置文件和本地配置文件,找出需要下載的文件和本地需要?jiǎng)h除的文件:
List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>();
//某些文件不再需要了,刪除
List<LocalFile> preDeleteFile = new List<LocalFile>();
foreach (LocalFile file in config.UpdateFileList)
{
??? if (listRemotFile.ContainsKey(file.Path))
??? {
??????? RemoteFile rf = listRemotFile[file.Path];
??????? if (rf.LastVer != file.LastVer)
??????? {
??????????? downloadList.Add(new DownloadFileInfo(rf.Url, file.Path, rf.LastVer, rf.Size));
??????????? file.LastVer = rf.LastVer;
??????????? file.Size = rf.Size;
??????????? if (rf.NeedRestart)
??????????????? bNeedRestart = true;
??????? }
??????? listRemotFile.Remove(file.Path);
??? }
??? else
??? {
??????? preDeleteFile.Add(file);
??? }
}
foreach (RemoteFile file in listRemotFile.Values)
{
??? downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size));
??? config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size));
??? if (file.NeedRestart)
??????? bNeedRestart = true;
}
如果發(fā)現(xiàn)有需要下載的文件,則向用戶顯示這些文件,并提示其是否馬上更新。如果用戶選擇了馬上更新,則先刪除本地不再需要的文件,然后開始下載更新文件。
if (downloadList.Count > 0)
{
??? DownloadConfirm dc = new DownloadConfirm(downloadList);
??? if (this.OnShow != null)
??????? this.OnShow();
??? if (DialogResult.OK == dc.ShowDialog())
??? {
??????? foreach (LocalFile file in preDeleteFile)
??????? {
??????????? string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.Path);
??????????? if (File.Exists(filePath))
??????????????? File.Delete(filePath);
??????????? config.UpdateFileList.Remove(file);
??????? }
??????? StartDownload(downloadList);
??? }
}
我們?cè)賮?lái)看一下StartDownload函數(shù)
private void StartDownload(List<DownloadFileInfo> downloadList)
{
??? DownloadProgress dp = new DownloadProgress(downloadList);
??? if (dp.ShowDialog() == DialogResult.OK)
??? {
??????? //更新成功
??????? config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FILENAME));
??????? if (bNeedRestart)
??????? {
??????????? MessageBox.Show("程序需要重新啟動(dòng)才能應(yīng)用更新,請(qǐng)點(diǎn)擊確定重新啟動(dòng)程序。", "自動(dòng)更新", MessageBoxButtons.OK, MessageBoxIcon.Information);
??????????? Process.Start(Application.ExecutablePath);
??????????? Environment.Exit(0);
??????? }
??? }
}
在這個(gè)函數(shù)中,先調(diào)用DownloadProgress下載所有需要下載的文件,然后更新本地配置文件,最后,如果發(fā)現(xiàn)某些更新文件需要重新啟動(dòng)應(yīng)用程序的話,會(huì)提示用戶重新啟動(dòng)程序。
至此,AutoUpdater這個(gè)類的使命就完成了,其實(shí),整個(gè)的升級(jí)過(guò)程也就完成了。(廢話)。
最后,我們來(lái)看一下這個(gè)組件是如何下載更新文件的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.IO;
using System.Diagnostics;
namespace Iyond.Utility
{
??? public partial class DownloadProgress : Form
??? {
??????? private bool isFinished = false;
??????? private List<DownloadFileInfo> downloadFileList = null;
??????? private ManualResetEvent evtDownload = null;
??????? private ManualResetEvent evtPerDonwload = null;
??????? private WebClient clientDownload = null;
??????? public DownloadProgress(List<DownloadFileInfo> downloadFileList)
??????? {
??????????? InitializeComponent();
??????????? this.downloadFileList = downloadFileList;
??????? }
??????? private void OnFormClosing(object sender, FormClosingEventArgs e)
??????? {
??????????? if (!isFinished && DialogResult.No == MessageBox.Show("當(dāng)前正在更新,是否取消?", "自動(dòng)升級(jí)", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
??????????? {
??????????????? e.Cancel = true;
??????????????? return;
??????????? }
??????????? else
??????????? {
??????????????? if (clientDownload != null)
??????????????????? clientDownload.CancelAsync();
??????????????? evtDownload.Set();
??????????????? evtPerDonwload.Set();
??????????? }
??????? }
??????? private void OnFormLoad(object sender, EventArgs e)
??????? {
??????????? evtDownload = new ManualResetEvent(true);
??????????? evtDownload.Reset();
??????????? Thread t = new Thread(new ThreadStart(ProcDownload));
??????????? t.Name = "download";
??????????? t.Start();
??????? }
??????? long total = 0;
??????? long nDownloadedTotal = 0;
??????? private void ProcDownload()
??????? {
??????????? evtPerDonwload = new ManualResetEvent(false);
??????????? foreach (DownloadFileInfo file in this.downloadFileList)
??????????? {
??????????????? total += file.Size;
??????????? }
??????????? while (!evtDownload.WaitOne(0, false))
??????????? {
??????????????? if (this.downloadFileList.Count == 0)
??????????????????? break;
??????????????? DownloadFileInfo file = this.downloadFileList[0];
??????????????? //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName));
??????????????? this.ShowCurrentDownloadFileName(file.FileName);
??????????????? //下載
??????????????? clientDownload = new WebClient();
??????????????? clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
??????????????? clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);
??????????????? evtPerDonwload.Reset();
??????????????? clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName + ".tmp"), file);
??????????????? //等待下載完成
??????????????? evtPerDonwload.WaitOne();
??????????????? clientDownload.Dispose();
??????????????? clientDownload = null;
??????????????? //移除已下載的文件
??????????????? this.downloadFileList.Remove(file);
??????????? }
??????????? //Debug.WriteLine("All Downloaded");
??????????? if (this.downloadFileList.Count == 0)
??????????????? Exit(true);
??????????? else
??????????????? Exit(false);
??????????? evtDownload.Set();
??????? }
??????? void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
??????? {
??????????? DownloadFileInfo file = e.UserState as DownloadFileInfo;
??????????? nDownloadedTotal += file.Size;
??????????? this.SetProcessBar(0, (int)(nDownloadedTotal * 100 / total));
??????????? //Debug.WriteLine(String.Format("Finish Download:{0}", file.FileName));
??????????? //替換現(xiàn)有文件
??????????? string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName);
??????????? if (File.Exists(filePath))
??????????? {
??????????????? if (File.Exists(filePath + ".old"))
??????????????????? File.Delete(filePath + ".old");
??????????????? File.Move(filePath, filePath + ".old");
??????????? }
??????????? File.Move(filePath + ".tmp", filePath);
??????????? //繼續(xù)下載其它文件
??????????? evtPerDonwload.Set();
??????? }
??????? void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
??????? {
??????????? this.SetProcessBar(e.ProgressPercentage, (int)((nDownloadedTotal + e.BytesReceived) * 100 / total));
??????? }
??????? delegate void ShowCurrentDownloadFileNameCallBack(string name);
??????? private void ShowCurrentDownloadFileName(string name)
??????? {
??????????? if (this.labelCurrentItem.InvokeRequired)
??????????? {
??????????????? ShowCurrentDownloadFileNameCallBack cb = new ShowCurrentDownloadFileNameCallBack(ShowCurrentDownloadFileName);
??????????????? this.Invoke(cb, new object[] { name });
??????????? }
??????????? else
??????????? {
??????????????? this.labelCurrentItem.Text = name;
??????????? }
??????? }
??????? delegate void SetProcessBarCallBack(int current, int total);
??????? private void SetProcessBar(int current, int total)
??????? {
??????????? if (this.progressBarCurrent.InvokeRequired)
??????????? {
??????????????? SetProcessBarCallBack cb = new SetProcessBarCallBack(SetProcessBar);
??????????????? this.Invoke(cb, new object[] { current, total });
??????????? }
??????????? else
??????????? {
??????????????? this.progressBarCurrent.Value = current;
??????????????? this.progressBarTotal.Value = total;
??????????? }
??????? }
??????? delegate void ExitCallBack(bool success);
??????? private void Exit(bool success)
??????? {
??????????? if (this.InvokeRequired)
??????????? {
??????????????? ExitCallBack cb = new ExitCallBack(Exit);
??????????????? this.Invoke(cb, new object[] { success });
??????????? }
??????????? else
??????????? {
??????????????? this.isFinished = success;
??????????????? this.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
??????????????? this.Close();
??????????? }
??????? }
??????? private void OnCancel(object sender, EventArgs e)
??????? {
??????????? evtDownload.Set();
??????????? evtPerDonwload.Set();
??????? }
??? }
}
在構(gòu)造函數(shù)中,將要下載的文件列表傳進(jìn)來(lái)
public DownloadProgress(List<DownloadFileInfo> downloadFileList)
{
??? InitializeComponent();
??? this.downloadFileList = downloadFileList;
}
在Form的Load事件中,啟動(dòng)下載線程,開始下載。
private void OnFormLoad(object sender, EventArgs e)
{
??? evtDownload = new ManualResetEvent(true);
??? evtDownload.Reset();
??? Thread t = new Thread(new ThreadStart(ProcDownload));
??? t.Name = "download";
??? t.Start();
}
下載線程沒什么特殊的,使用了WebClient的異步下載文件函數(shù)DownloadFileAsync,并且注冊(cè)了兩個(gè)事件,分別負(fù)責(zé)下載進(jìn)度顯示和下載完成后的處理:
clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);
大家看一下就明白了。
private void ProcDownload()
{
??? evtPerDonwload = new ManualResetEvent(false);
??? foreach (DownloadFileInfo file in this.downloadFileList)
??? {
??????? total += file.Size;
??? }
??? while (!evtDownload.WaitOne(0, false))
??? {
??????? if (this.downloadFileList.Count == 0)
??????????? break;
??????? DownloadFileInfo file = this.downloadFileList[0];
??????? //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName));
??????? this.ShowCurrentDownloadFileName(file.FileName);
??????? //下載
??????? clientDownload = new WebClient();
??????? clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
??????? clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);
??????? evtPerDonwload.Reset();
??????? clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName + ".tmp"), file);
??????? //等待下載完成
??????? evtPerDonwload.WaitOne();
??????? clientDownload.Dispose();
??????? clientDownload = null;
??????? //移除已下載的文件
??????? this.downloadFileList.Remove(file);
??? }
??? //Debug.WriteLine("All Downloaded");
??? if (this.downloadFileList.Count == 0)
??????? Exit(true);
??? else
??????? Exit(false);
??? evtDownload.Set();
}
最后,在OnDownloadFileCompleted函數(shù)中進(jìn)行最后的處理。包括備份原文件,替換現(xiàn)有文件等。
void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
??? DownloadFileInfo file = e.UserState as DownloadFileInfo;
??? nDownloadedTotal += file.Size;
??? this.SetProcessBar(0, (int)(nDownloadedTotal * 100 / total));
??? //Debug.WriteLine(String.Format("Finish Download:{0}", file.FileName));
??? //替換現(xiàn)有文件
??? string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName);
??? if (File.Exists(filePath))
??? {
??????? if (File.Exists(filePath + ".old"))
??????????? File.Delete(filePath + ".old");
??????? File.Move(filePath, filePath + ".old");
??? }
??? File.Move(filePath + ".tmp", filePath);
??? //繼續(xù)下載其它文件
??? evtPerDonwload.Set();
}
其它的函數(shù)只是一些顯示進(jìn)度條和下載信息的,這里就不再詳細(xì)介紹了。
轉(zhuǎn)載于:https://www.cnblogs.com/AllenCheung/archive/2009/07/12/1521896.html
總結(jié)
以上是生活随笔為你收集整理的c# 智能升级程序代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: md5加密算法的C(C++)代码实现
- 下一篇: c#基础知识总结学习