感谢csdn jekytan 的共享 http://download.csdn.net/detail/jekytan/4242666
本地xml文件
<?xml version="1.0" encoding="utf-8"?> <AutoUpdater> <AppName>WinUpdate</AppName> <ReleaseURL>http://127.0.0.1/webdown/</ReleaseURL> <ReleaseDate>2012/3/1 10:42:34</ReleaseDate> <ReleaseVersion>1.0.1.99</ReleaseVersion> <MinVersion>1.0.1.88</MinVersion> <UpdateDes> 1、 添加打印菜单 2、 增加DLL 3、增加关于模块 </UpdateDes> <ApplicationStart>WinUpdate.exe</ApplicationStart> <ShortcutIcon>ico</ShortcutIcon> <Releases> <File name="AboutForm.dll" date="2012/2/21 10:07:31" size="39" /> </Releases> </AutoUpdater>
服务器xml文件
<?xml version="1.0" encoding="utf-8" ?> - <AutoUpdater> <AppName>WinUpdate</AppName> <ReleaseURL>http://127.0.0.1/webdown/</ReleaseURL> <ReleaseDate>2012/3/1 10:42:34</ReleaseDate> <ReleaseVersion>1.0.4.98</ReleaseVersion> <MinVersion>1.0.1.88</MinVersion> <UpdateDes>1、 添加打印菜单 2、 增加DLL 3、增加关于模块</UpdateDes> <ApplicationStart>WinUpdate.exe</ApplicationStart> <ShortcutIcon>WMS.ico</ShortcutIcon> - <Releases> <File name="AboutForm.dll" date="2012/3/25 10:07:31" size="100" /> <File name="WinUpdate.exe" date="2012/3/25 10:07:31" size="39" /> </Releases> </AutoUpdater>
服务器文件webdown放到IIS127.0.0.1中的根目录下即可
前台
后台
string tempPath; ReleaseList localRelease; ReleaseList remoteRelease; ReleaseFile[] diff; bool downloaded; int totalSize; const string RetryText = " 重 试 "; const string FinishText = " 完 成 "; public UpdateForm() { InitializeComponent(); } public UpdateForm( string tempPath, ReleaseList localRelease, ReleaseList remoteRelease ) { InitializeComponent(); this.tempPath = tempPath; this.localRelease = localRelease; this.remoteRelease = remoteRelease; } private void UpdateForm_Load(object sender, EventArgs e) { Init(); } private void Init() { label2.Text = "下载进度"; label1.Text = string.Format("当前版本:{0} 最新版本:{1} 发布时间:{2}", localRelease.ReleaseVersion, remoteRelease.ReleaseVersion, remoteRelease.ReleaseDate); //升级内容 textBox1.Text = remoteRelease.UpdateDescription; diff = localRelease.GetDifferences(remoteRelease, out totalSize); if (diff == null) { button1.Text = "升级完成!"; return; } progressBar1.Maximum = totalSize * 1024; progressBar1.Step = 10; Upgrade(); } Thread trd; private void Upgrade() { trd = new Thread(new ThreadStart(DoUpgrade)); trd.IsBackground = true; trd.Start(); } private void DoUpgrade() { downloaded = false; progressBar1.Value = 0; foreach (ReleaseFile file in diff) { try { DownloadTool.DownloadFile(tempPath, remoteRelease.ReleaseUrl +remoteRelease.ReleaseVersion, file.FileName, progressBar1, label2); } catch (Exception ex) { AppTool.DeleteTempFolder(tempPath); MessageBox.Show(file.FileName + "下载失败,请稍后再试"); OptionalUpdate = true; trd.Abort(); return; } } try { foreach (ReleaseFile file in diff) { string dir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + file.FileName); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } File.Copy(tempPath + file.FileName, AppDomain.CurrentDomain.BaseDirectory + file.FileName, true); } } catch (Exception ex) { AppTool.DeleteTempFolder(tempPath); MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); OptionalUpdate = true; trd.Abort(); return; } remoteRelease.Save(localRelease.FileName); downloaded = true; CreateShortcut(); Application.Exit(); AppTool.Start(localRelease.ApplicationStart); trd.Abort(); } private bool OptionalUpdate { set { ; } } private void CreateShortcut() { string fileName = remoteRelease.AppName; foreach (char invalidChar in Path.GetInvalidFileNameChars()) { fileName = fileName.Replace(invalidChar, '_'); } string path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\" + fileName + ".lnk"; if (File.Exists(path)) return; } private void UpdateForm_FormClosing(object sender, FormClosingEventArgs e) { AppTool.DeleteTempFolder(tempPath); } private void button2_Click(object sender, EventArgs e) { Application.Exit(); AppTool.Start(localRelease.ApplicationStart); } private void button1_Click(object sender, EventArgs e) { button1.Enabled = false; Upgrade(); }
DownloadTool.cs类
public class DownloadTool { public static void DownloadFile(string localFolder, string remoteFolder, string fileName) { //if (!System.IO.Directory.Exists(localFolder)) // System.IO.Directory.CreateDirectory(localFolder); string url = remoteFolder+ fileName; string path = localFolder + fileName; string dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); var wc = new WebClient(); wc.DownloadFile(url, path); } public static string FormatFileSizeDescription(int bytes) { if (bytes > 1024 * 1024) return string.Format("{0}M", Math.Round((double)bytes / (1024 * 1024), 2, MidpointRounding.AwayFromZero)); if (bytes > 1024) return string.Format("{0}K", Math.Round((double)bytes / 1024, 2, MidpointRounding.AwayFromZero)); return string.Format("{0}B", bytes); } public static void DownloadFile(string localFolder, string remoteFolder, string fileName, ProgressBar bar, Label lblSize) { Thread.Sleep(5000);//真正用的时候把此行注释掉,现在是为了模拟进度条 string url = remoteFolder + "/" + fileName; string path = localFolder+ fileName; string dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); WebRequest req = WebRequest.Create(url); WebResponse res = req.GetResponse(); if (res.ContentLength == 0) return; long fileLength = res.ContentLength; string totalSize = FormatFileSizeDescription(bar.Maximum); using (Stream srm = res.GetResponseStream()) { var srmReader = new StreamReader(srm); var bufferbyte = new byte[fileLength]; int allByte = bufferbyte.Length; int startByte = 0; while (fileLength > 0) { int downByte = srm.Read(bufferbyte, startByte, allByte); if (downByte == 0) { break; } ; startByte += downByte; allByte -= downByte; int progress = bar.Value + downByte; progress = progress > bar.Maximum ? bar.Maximum : progress; //bar.BeginInvoke(new invoke(setbar)); //bar.Value = progress; //lblSize.Text = string.Format("已完成{0}/{1}", FormatFileSizeDescription(progress), totalSize); //float part = (float)startByte / 1024; //float total = (float)bufferbyte.Length / 1024; //int percent = Convert.ToInt32((part / total) * 100); } var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); fs.Write(bufferbyte, 0, bufferbyte.Length); srm.Close(); srmReader.Close(); fs.Close(); } } public void setbar() { } } internal class AppTool { public static void Start(string appName) { Process.Start(appName, "ok"); } internal static void DeleteTempFolder(string folder) { try { Directory.Delete(folder, true); } catch { } } }
program.cs类
public const string UPDATER_EXE_NAME = "AutoUpdate.exe"; public const string ReleaseConfigFileName = "ReleaseList.xml"; private static ReleaseList localRelease; private static ReleaseList remoteRelease; private static string tempPath; /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //获取本地relealist文件信息 string localXmlPath = string.Format("{0}\\{1}", Application.StartupPath, ReleaseConfigFileName); localRelease = new ReleaseList(localXmlPath); tempPath = Path.GetTempPath(); try { //下载服务器上的relealist文件 DownloadTool.DownloadFile(tempPath, localRelease.ReleaseUrl, ReleaseConfigFileName); } catch (WebException ex) { AppTool.DeleteTempFolder(tempPath); Application.Exit(); AppTool.Start(localRelease.ApplicationStart); return; } catch { AppTool.DeleteTempFolder(tempPath); MessageBox.Show("下载更新文件失败,请检查网络和文件夹权限"); Application.Exit(); return; } //把relealist.xml文件下载到本地后,从本地读取 remoteRelease = new ReleaseList(tempPath + ReleaseConfigFileName); //比较本机文件和服务器上的XML文件 if (localRelease.Compare(remoteRelease) != 0) { if (CheckProcessing() != DialogResult.OK) { AppTool.DeleteTempFolder(tempPath); Application.Exit(); return; } UpdateForm form = new UpdateForm(tempPath, localRelease, remoteRelease); Application.Run(form); } else { AppTool.DeleteTempFolder(tempPath); Application.Exit(); AppTool.Start(localRelease.ApplicationStart); } } /// <summary> /// 判断现在是否有主项目在运行 /// </summary> /// <returns></returns> static DialogResult CheckProcessing() { string exeName = localRelease.ApplicationStart.Substring(0, localRelease.ApplicationStart.Length - 4); if (Process.GetProcessesByName(exeName).Length > 0) { var rs = MessageBox.Show(string.Format("请先退出正在运行的{0}", exeName), "警告", MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1); if (rs == DialogResult.Retry) { return CheckProcessing(); } return rs; } return DialogResult.OK; } }
repleaselist.cs类
private readonly string fileName; private string applicationStart; private string appName; private IList<ReleaseFile> files; private string minVersion; private string releaseDate; private string releaseUrl; private string releaseVersion; private string shortcutIcon; private string updateDes; public ReleaseList() { LoadXml( @"<?xml version=""1.0"" encoding=""utf-8""?> <AutoUpdater> <AppName></AppName> <ReleaseURL></ReleaseURL> <ReleaseDate></ReleaseDate> <ReleaseVersion></ReleaseVersion> <MinVersion></MinVersion> <UpdateDes></UpdateDes> <ApplicationStart></ApplicationStart> <ShortcutIcon></ShortcutIcon> <Releases> </Releases> </AutoUpdater> "); } public ReleaseList(string filePath) { fileName = filePath; Load(filePath); appName = GetNodeValue("/AutoUpdater/AppName"); releaseDate = GetNodeValue("/AutoUpdater/ReleaseDate"); releaseUrl = GetNodeValue("/AutoUpdater/ReleaseURL"); releaseVersion = GetNodeValue("/AutoUpdater/ReleaseVersion"); minVersion = GetNodeValue("/AutoUpdater/MinVersion"); updateDes = GetNodeValue("/AutoUpdater/UpdateDes"); applicationStart = GetNodeValue("/AutoUpdater/ApplicationStart"); shortcutIcon = GetNodeValue("/AutoUpdater/ShortcutIcon"); XmlNodeList fileNodes = GetNodeList("/AutoUpdater/Releases"); files = new List<ReleaseFile>(); foreach (XmlNode node in fileNodes) { files.Add(new ReleaseFile(node.Attributes[0].Value, node.Attributes[1].Value, Convert.ToInt32(node.Attributes[2].Value))); } } /// <summary> /// 应用程序名 /// </summary> public string AppName { set { appName = value; SetNodeValue("AutoUpdater/AppName", value); } get { return appName; } } /// <summary> /// 文件名 /// </summary> public string FileName { get { return fileName; } } /// <summary> /// 发布url /// </summary> public string ReleaseUrl { get { return releaseUrl; } set { releaseUrl = value; SetNodeValue("AutoUpdater/ReleaseURL", value); } } /// <summary> /// 发布日期 /// </summary> public string ReleaseDate { get { return releaseDate; } set { releaseDate = value; SetNodeValue("AutoUpdater/ReleaseDate", value); } } //版本号 public string ReleaseVersion { get { return releaseVersion; } set { releaseVersion = value; SetNodeValue("AutoUpdater/ReleaseVersion", value); } } //最小版本号 public string MinVersion { get { return minVersion; } set { minVersion = value; SetNodeValue("AutoUpdater/MinVersion", value); } } //升级内容 public string UpdateDescription { get { return updateDes; } set { updateDes = value; SetNodeValue("AutoUpdater/UpdateDes", value); } } //应用程序图标 public string ShortcutIcon { get { return shortcutIcon; } set { shortcutIcon = value; SetNodeValue("AutoUpdater/ShortcutIcon", value); } } //启动程序 public string ApplicationStart { get { return applicationStart; } set { applicationStart = value; SetNodeValue("AutoUpdater/ApplicationStart", value); } } //升级文件集合 public IList<ReleaseFile> Files { get { return files; } set { files = value; RefreshFileNodes(); } } //版本号比较 public int Compare(string version) { string[] myVersion = releaseVersion.Split('.'); string[] otherVersion = version.Split('.'); int i = 0; foreach (string v in myVersion) { int myNumber = int.Parse(v); int otherNumber = int.Parse(otherVersion[i]); if (myNumber != otherNumber) return myNumber - otherNumber; i++; } return 0; } //版本号北京 public int Compare(ReleaseList otherList) { if (otherList == null) throw new ArgumentNullException("otherList"); int diff = Compare(otherList.ReleaseVersion); if (diff != 0) return diff; return (releaseDate == otherList.ReleaseDate) ? 0 : (DateTime.Parse(releaseDate) > DateTime.Parse(otherList.ReleaseDate) ? 1 : -1); } /// <summary> /// 版本号比较,并输出总文件大小 /// </summary> /// <param name="otherList"></param> /// <param name="fileSize"></param> /// <returns></returns> public ReleaseFile[] GetDifferences(ReleaseList otherList, out int fileSize) { fileSize = 0; if (otherList == null || Compare(otherList) == 0) return null; var ht = new Hashtable(); foreach (ReleaseFile file in files) { ht.Add(file.FileName, file.ReleaseDate); } var diffrences = new List<ReleaseFile>(); foreach (ReleaseFile file in otherList.files) { //如果本地的XML文件中不包括服务器上要升级的文件或者服务器的文件的发布日期大于本地XML文件的发布日期,开始升级 if (!ht.ContainsKey(file.FileName) || DateTime.Parse(file.ReleaseDate) > DateTime.Parse(ht[file.FileName].ToString())) { diffrences.Add(file); fileSize += file.FileSize; } } return diffrences.ToArray(); } /// <summary> /// 给定一个节点的xPath表达式并返回一个节点 /// </summary> /// <param name="node"></param> /// <returns></returns> public XmlNode FindNode(string xPath) { XmlNode xmlNode = SelectSingleNode(xPath); return xmlNode; } /// <summary> /// 给定一个节点的xPath表达式返回其值 /// </summary> /// <param name="xPath"></param> /// <returns></returns> public string GetNodeValue(string xPath) { XmlNode xmlNode = SelectSingleNode(xPath); return xmlNode.InnerText; } public void SetNodeValue(string xPath, string value) { XmlNode xmlNode = SelectSingleNode(xPath); xmlNode.InnerXml = value; } /// <summary> /// 给定一个节点的表达式返回此节点下的孩子节点列表 /// </summary> /// <param name="xPath"></param> /// <returns></returns> public XmlNodeList GetNodeList(string xPath) { XmlNodeList nodeList = SelectSingleNode(xPath).ChildNodes; return nodeList; } public void RefreshFileNodes() { if (files == null) return; XmlNode node = SelectSingleNode("AutoUpdater/Releases"); node.RemoveAll(); foreach (ReleaseFile file in files) { XmlElement el = CreateElement("File"); XmlAttribute attrName = CreateAttribute("name"); attrName.Value = file.FileName; XmlAttribute attrDate = CreateAttribute("date"); attrDate.Value = file.ReleaseDate; XmlAttribute attrSize = CreateAttribute("size"); attrSize.Value = file.FileSize.ToString(); el.Attributes.Append(attrName); el.Attributes.Append(attrDate); el.Attributes.Append(attrSize); node.AppendChild(el); } } } /// <summary> /// 发布的文件信息 /// </summary> public class ReleaseFile { public ReleaseFile() { } /// <summary> /// 文 /// </summary> /// <param name="fileName">文件名称</param> /// <param name="releaseDate">发布日期</param> /// <param name="fileSize">大小</param> public ReleaseFile(string fileName, string releaseDate, int fileSize) { this.FileName = fileName; this.ReleaseDate = releaseDate; this.FileSize = fileSize; } public string FileName { get; set; } public string ReleaseDate { get; set; } public int FileSize { get; set; } }