Winform(C#.NET)自动更新组件的使用及部分功能实现

声明:核心功能的实现是由园子里圣殿骑士大哥写的,本人是基于他核心代码,按照自己需求进行修改的。

     而AutoUpdaterService.xml文件生成工具是基于评论#215楼 ptangbao的代码而改写的。

由于这个组件是在10年写的,.net也有更新有的方法已提示过时,更改如下:

//Added the function to support proxy
//clientDownload.Proxy = System.Net.WebProxy.GetDefaultProxy();
clientDownload.Proxy = WebRequest.GetSystemWebProxy();

更改的主要功能如下:

  1》如果有更新将会直接更新,不再提供由用户点击确定后再更新。(强制更新)(这个暂时没有整理出来,后续会整理出来)

  2》更新前判断主程序进程是否开启:

  如果有更新,主程序开启,关闭主程序,更新完成后自动启动主程序。

  如果没有更新,直接启动主程序。

  3》不再根据版本号不同进行更新。

  圣殿骑士大哥的是根据版本号,当然这也是最正规的,可是我们的程序有点特殊,所以不再根据版本号控制,而是根据GUID。

  这样就是有一点好处不管版本号一不一样,只要GUID不一样就是要更新。

  比如文件夹如下:

  

  使用CreateXmlTools.exe工具生成xml文件,增加的节点属性有version,值时GUID

<?xml version="1.0" encoding="utf-8"?>
<updateFiles>
  <file path="AutoUpdater.dll" url="http://172.30.100.55:8011/AutoUpdater.dll" lastver="5.0.0.0" size="26624" needRestart="false" version="1ef2b9dc-d14f-4fc4-a5ec-bdb07a6ba98c" />
  <file path="ReadMe.dll" url="http://172.30.100.55:8011/ReadMe.dll" lastver="" size="472" needRestart="false" version="3ddc1926-3088-468f-9088-92b07156c757" />
  <file path="aspnet_client/ReadMe.dll" url="http://172.30.100.55:8011/aspnet_client/ReadMe.dll" lastver="" size="472" needRestart="false" version="4aaa87e2-63bd-486a-9957-1c2df21607cb" />
</updateFiles>

  version就是用来替代lastver的,只要不一样就更新

  4》客户端更新主程序更改autoupdater.config文件的更新方式

  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://172.30.100.55:8011/AutoupdateService.xml</ServerUrl>
  <UpdateFileList>
    
  </UpdateFileList>
</Config>

  ServerUrl就是web服务器的地址加上面生成xml文件的地址。

  更新完成后客户端会自动更新autoupdater.config文件,将本地的guid保持与服务端一致,再次点击guid一致的不再更新

以上是大致改动的地方。

下面来说说代码吧:

由于增加了GUID这块,所以RemoteFile、LocalFile和DownloadFileInfo三个实体类都应该增加一个字段和一个属性

LocalFile.cs

 1     public class LocalFile
 2     {
 3         #region The private fields
 4         private string path = "";
 5         private string lastver = "";
 6         private int size = 0;
 7         private string version = "";
 8         #endregion
 9 
10         #region The public property
11         [XmlAttribute("path")]
12         public string Path { get { return path; } set { path = value; } }
13         [XmlAttribute("lastver")]
14         public string LastVer { get { return lastver; } set { lastver = value; } }
15         [XmlAttribute("size")]
16         public int Size { get { return size; } set { size = value; } }
17         [XmlAttribute("version")]
18         public string Version { get { return version; } set { version = value; } }
19         #endregion
20 
21         #region The constructor of LocalFile
22         public LocalFile(string path, string ver, int size,string versionid)
23         {
24             this.path = path;
25             this.lastver = ver;
26             this.size = size;
27             this.version = versionid;
28         }
29 
30         public LocalFile()
31         {
32         }
33         #endregion
34 
35     }
View Code

RemoteFile.cs

 1     public class RemoteFile
 2     {
 3         #region The private fields
 4         private string path = "";
 5         private string url = "";
 6         private string lastver = "";
 7         private int size = 0;
 8         private bool needRestart = false;
 9         private string version = "";
10         #endregion
11 
12         #region The public property
13         public string Path { get { return path; } }
14         public string Url { get { return url; } }
15         public string LastVer { get { return lastver; } }
16         public int Size { get { return size; } }
17         public bool NeedRestart { get { return needRestart; } }
18         public string Verison { get { return version; } }
19         #endregion
20 
21         #region The constructor of AutoUpdater
22         public RemoteFile(XmlNode node)
23         {
24             this.path = node.Attributes["path"].Value;
25             this.url = node.Attributes["url"].Value;
26             this.lastver = node.Attributes["lastver"].Value;
27             this.size = Convert.ToInt32(node.Attributes["size"].Value);
28             this.needRestart = Convert.ToBoolean(node.Attributes["needRestart"].Value);
29             this.version = node.Attributes["version"].Value;
30         }
31         #endregion
32     }
View Code

DownloadFileInfo.cs

 1     public class DownloadFileInfo
 2     {
 3         #region The private fields
 4         string downloadUrl = string.Empty;
 5         string fileName = string.Empty;
 6         string lastver = string.Empty;
 7         int size = 0;
 8         string version = string.Empty;
 9         #endregion
10 
11         #region The public property
12         public string DownloadUrl { get { return downloadUrl; } }
13         public string FileFullName { get { return fileName; } }
14         public string FileName { get { return Path.GetFileName(FileFullName); } }
15         public string LastVer { get { return lastver; } set { lastver = value; } }
16         public int Size { get { return size; } }
17         public string Version { get { return version; } set { version = value; } }
18         #endregion
19 
20         #region The constructor of DownloadFileInfo
21         public DownloadFileInfo(string url, string name, string ver, int size,string versionid)
22         {
23             this.downloadUrl = url;
24             this.fileName = name;
25             this.lastver = ver;
26             this.size = size;
27             this.version = versionid;
28         }
29         #endregion
30     }
View Code

ConstFile.cs

一些常量配置文件

CommonUnitity.cs

//主要是更改获取多层目录文件夹路径
public
static string GetFolderUrl(DownloadFileInfo file) { string folderPathUrl = string.Empty; int folderPathPoint = file.DownloadUrl.IndexOf("/", 15) + 1; string filepathstring = file.DownloadUrl.Substring(folderPathPoint); //int folderPathPoint1 = filepathstring.IndexOf("/"); //string filepathstring1 = filepathstring.Substring(folderPathPoint1 + 1); //if(filepathstring1.IndexOf("/") != -1) if(filepathstring.IndexOf("/") != -1) { //string[] ExeGroup = filepathstring1.Split('/'); string[] ExeGroup = filepathstring.Split('/'); for (int i = 0; i < ExeGroup.Length - 1; i++) { folderPathUrl += "\\" + ExeGroup[i]; } if (!Directory.Exists(SystemBinUrl + ConstFile.TEMPFOLDERNAME + folderPathUrl)) { Directory.CreateDirectory(SystemBinUrl + ConstFile.TEMPFOLDERNAME + folderPathUrl); } } return folderPathUrl; }

autoupdater.cs

  1 public class AutoUpdater : IAutoUpdater
  2     {
  3         #region The private fields
  4         private Config config = null;
  5         private bool bNeedRestart = false;
  6         private bool bDownload = false;
  7         List<DownloadFileInfo> downloadFileListTemp = null;
  8         #endregion
  9 
 10         #region The public event
 11         public event ShowHandler OnShow;
 12         #endregion
 13 
 14         #region The constructor of AutoUpdater
 15         public AutoUpdater()
 16         {
 17             config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME));
 18         }
 19         #endregion
 20 
 21         #region The public method
 22         public void Update()
 23         {
 24             if (!config.Enabled)
 25                 return;
 26 
 27             Dictionary<string, RemoteFile> listRemotFile = ParseRemoteXml(config.ServerUrl);
 28             List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>();
 29 
 30             foreach (LocalFile file in config.UpdateFileList)
 31             {
 32                 if (listRemotFile.ContainsKey(file.Path))
 33                 {
 34                     RemoteFile rf = listRemotFile[file.Path];
 35                     //Version v1 = new Version(rf.LastVer);
 36                     //Version v2 = new Version(file.LastVer);
 37                     //if (v1 > v2)
 38                     string v1 = rf.Verison;
 39                     string v2 = file.Version;
 40                     if (v1 != v2)
 41                     {
 42                         downloadList.Add(new DownloadFileInfo(rf.Url, rf.Path, rf.LastVer, rf.Size, rf.Verison));
 43                         file.Path = rf.Path;
 44                         file.LastVer = rf.LastVer;
 45                         file.Size = rf.Size;
 46                         file.Version = rf.Verison;
 47                         if (rf.NeedRestart)
 48                             bNeedRestart = true;
 49 
 50                         bDownload = true;
 51                     }
 52 
 53                     listRemotFile.Remove(file.Path);
 54                 }
 55             }
 56 
 57             foreach (RemoteFile file in listRemotFile.Values)
 58             {
 59                 downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size, file.Verison));
 60                 bDownload = true;
 61                 config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size, file.Verison));
 62                 if (file.NeedRestart)
 63                     bNeedRestart = true;
 64             }
 65 
 66             downloadFileListTemp = downloadList;
 67 
 68             if (bDownload)
 69             {
 70                 OperProcess op = new OperProcess();
 71                 op.InitUpdateEnvironment();
 72                 DownloadConfirm dc = new DownloadConfirm(downloadList);
 73 
 74                 if (this.OnShow != null)
 75                     this.OnShow();
 76                 StartDownload(downloadList);
 77             }
 78         }
 79 
 80         public void RollBack()
 81         {
 82             foreach (DownloadFileInfo file in downloadFileListTemp)
 83             {
 84                 string tempUrlPath = CommonUnitity.GetFolderUrl(file);
 85                 string oldPath = string.Empty;
 86                 try
 87                 {
 88                     if (!string.IsNullOrEmpty(tempUrlPath))
 89                     {
 90                         oldPath = Path.Combine(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(1), file.FileName);
 91                     }
 92                     else
 93                     {
 94                         oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName);
 95                     }
 96 
 97                     if (oldPath.EndsWith("_"))
 98                         oldPath = oldPath.Substring(0, oldPath.Length - 1);
 99 
100                     MoveFolderToOld(oldPath + ".old", oldPath);
101 
102                 }
103                 catch (Exception ex)
104                 {
105                     //log the error message,you can use the application's log code
106                 }
107             }
108         }
109 
110 
111         #endregion
112 
113         #region The private method
114         string newfilepath = string.Empty;
115         private void MoveFolderToOld(string oldPath, string newPath)
116         {
117             if (File.Exists(oldPath) && File.Exists(newPath))
118             {
119                 System.IO.File.Copy(oldPath, newPath, true);
120             }
121         }
122 
123         private void StartDownload(List<DownloadFileInfo> downloadList)
124         {
125             DownloadProgress dp = new DownloadProgress(downloadList);
126             if (dp.ShowDialog() == DialogResult.OK)
127             {
128                 //
129                 if (DialogResult.Cancel == dp.ShowDialog())
130                 {
131                     return;
132                 }
133                 //Update successfully
134                 config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME));
135 
136                 if (bNeedRestart)
137                 {
138                     //Delete the temp folder
139                     Directory.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.TEMPFOLDERNAME), true);
140 
141                     MessageBox.Show(ConstFile.APPLYTHEUPDATE, ConstFile.MESSAGETITLE, MessageBoxButtons.OK, MessageBoxIcon.Information);
142                     CommonUnitity.RestartApplication();
143                 }
144             }
145         }
146 
147         private Dictionary<string, RemoteFile> ParseRemoteXml(string xml)
148         {
149             XmlDocument document = new XmlDocument();
150             document.Load(xml);
151 
152             Dictionary<string, RemoteFile> list = new Dictionary<string, RemoteFile>();
153             foreach (XmlNode node in document.DocumentElement.ChildNodes)
154             {
155                 list.Add(node.Attributes["path"].Value, new RemoteFile(node));
156             }
157 
158             return list;
159         }
160         #endregion
161 
162     }
View Code

OperProcess.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Diagnostics;
 6 
 7 namespace AutoUpdater
 8 {
 9     /// <summary>
10     /// 启动进程、关闭进程操作
11     /// </summary>
12     public class OperProcess
13     {
14         #region init update env
15         public void InitUpdateEnvironment()
16         {
17             if (IfExist("MainProgram"))
18             {
19                 CloseExe("MainProgram");
20             }
21         }
22         #endregion init update env
23 
24         #region updated start process
25         public void StartProcess()
26         {
27             string path = System.Environment.CurrentDirectory;
28             if (!IfExist("MainProgram"))
29             {
30                 StartExe(path, "MainProgram.exe");
31             }
32             CloseExe("KnightsWarrior");
33         }
34 
35         #endregion
36 
37         #region 启动进程、关闭进程、判断进程是否存在
38         //启动exe绝对路径
39         private void StartExe(string filePath, string fileName)
40         {
41             Process proc = new Process();
42             proc.StartInfo.UseShellExecute = true;//是否使用操作系统外壳程序启动进程
43 
44             proc.StartInfo.WorkingDirectory = filePath;//启动进程的初始目录
45             proc.StartInfo.FileName = fileName;
46             proc.Start();
47         }
48 
49 
50         //exeName 关闭的exe进程名
51         private void CloseExe(string exeName)
52         {
53             Process[] arrPro = Process.GetProcessesByName(exeName);
54             foreach (Process pro in arrPro)
55                 pro.Kill();
56         }
57         //processName 进程名
58         private bool IfExist(string processName)
59         {
60             Process[] pro = Process.GetProcessesByName(processName);
61             return pro.Count() > 0;
62         }
63         #endregion 启动进程、关闭进程
64     }
65 }
View Code

DownloadProgress.cs

  1 public partial class DownloadProgress : Form
  2     {
  3         #region The private fields
  4         private bool isFinished = false;
  5         private List<DownloadFileInfo> downloadFileList = null;
  6         private List<DownloadFileInfo> allFileList = null;
  7         private ManualResetEvent evtDownload = null;
  8         private ManualResetEvent evtPerDonwload = null;
  9         private WebClient clientDownload = null;
 10         #endregion
 11 
 12         #region The constructor of DownloadProgress
 13         public DownloadProgress(List<DownloadFileInfo> downloadFileListTemp)
 14         {
 15             InitializeComponent();
 16 
 17             this.downloadFileList = downloadFileListTemp;
 18             allFileList = new List<DownloadFileInfo>();
 19             foreach (DownloadFileInfo file in downloadFileListTemp)
 20             {
 21                 allFileList.Add(file);
 22             }
 23         }
 24         #endregion
 25 
 26         #region The method and event
 27         private void OnFormClosing(object sender, FormClosingEventArgs e)
 28         {
 29             if (!isFinished && DialogResult.No == MessageBox.Show(ConstFile.CANCELORNOT, ConstFile.MESSAGETITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
 30             {
 31                 e.Cancel = true;
 32                 return;
 33             }
 34             else
 35             {
 36                 if (clientDownload != null)
 37                     clientDownload.CancelAsync();
 38 
 39                 evtDownload.Set();
 40                 evtPerDonwload.Set();
 41             }
 42         }
 43 
 44         private void OnFormLoad(object sender, EventArgs e)
 45         {
 46             evtDownload = new ManualResetEvent(true);
 47             evtDownload.Reset();
 48             ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcDownload));
 49         }
 50 
 51         long total = 0;
 52         long nDownloadedTotal = 0;
 53 
 54         private void ProcDownload(object o)
 55         {
 56             string tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
 57             if (!Directory.Exists(tempFolderPath))
 58             {
 59                 Directory.CreateDirectory(tempFolderPath);
 60             }
 61 
 62 
 63             evtPerDonwload = new ManualResetEvent(false);
 64 
 65             foreach (DownloadFileInfo file in this.downloadFileList)
 66             {
 67                 total += file.Size;
 68             }
 69             try
 70             {
 71                 while (!evtDownload.WaitOne(0, false))
 72                 {
 73                     if (this.downloadFileList.Count == 0)
 74                         break;
 75 
 76                     DownloadFileInfo file = this.downloadFileList[0];
 77 
 78 
 79                     //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName));
 80 
 81                     this.ShowCurrentDownloadFileName(file.FileName);
 82 
 83                     //Download
 84                     clientDownload = new WebClient();
 85 
 86                     //Added the function to support proxy
 87                     //clientDownload.Proxy = System.Net.WebProxy.GetDefaultProxy();
 88                     clientDownload.Proxy = WebRequest.GetSystemWebProxy();
 89                     clientDownload.Proxy.Credentials = CredentialCache.DefaultCredentials;
 90                     clientDownload.Credentials = System.Net.CredentialCache.DefaultCredentials;
 91                     //End added
 92 
 93                     clientDownload.DownloadProgressChanged += (object sender, DownloadProgressChangedEventArgs e) =>
 94                     {
 95                         try
 96                         {
 97                             this.SetProcessBar(e.ProgressPercentage, (int)((nDownloadedTotal + e.BytesReceived) * 100 / total));
 98                         }
 99                         catch
100                         {
101                             //log the error message,you can use the application's log code
102                         }
103 
104                     };
105 
106                     clientDownload.DownloadFileCompleted += (object sender, AsyncCompletedEventArgs e) =>
107                     {
108                         try
109                         {
110                             DealWithDownloadErrors();
111                             DownloadFileInfo dfile = e.UserState as DownloadFileInfo;
112                             nDownloadedTotal += dfile.Size;
113                             this.SetProcessBar(0, (int)(nDownloadedTotal * 100 / total));
114                             evtPerDonwload.Set();
115                         }
116                         catch (Exception)
117                         {
118                             //log the error message,you can use the application's log code
119                         }
120 
121                     };
122                     
123                     evtPerDonwload.Reset();
124 
125                     //Download the folder file
126                     string tempFolderPath1 = CommonUnitity.GetFolderUrl(file);
127                     if (!string.IsNullOrEmpty(tempFolderPath1))
128                     {
129                         tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
130                         tempFolderPath += tempFolderPath1;
131                     }
132                     else
133                     {
134                         tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
135                     }
136                     
137                     clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(tempFolderPath, file.FileName), file);
138                     //Wait for the download complete
139                     evtPerDonwload.WaitOne();
140 
141                     clientDownload.Dispose();
142                     clientDownload = null;
143 
144                     //Remove the downloaded files
145                     this.downloadFileList.Remove(file);
146                 }
147 
148             }
149             catch (Exception)
150             {
151                 ShowErrorAndRestartApplication();
152                 //throw;
153             }
154 
155             //When the files have not downloaded,return.
156             if (downloadFileList.Count > 0)
157             {
158                 return;
159             }
160 
161             //Test network and deal with errors if there have 
162             DealWithDownloadErrors();
163 
164             //Debug.WriteLine("All Downloaded");
165             foreach (DownloadFileInfo file in this.allFileList)
166             {
167                 string tempUrlPath = CommonUnitity.GetFolderUrl(file);
168                 string oldPath = string.Empty;
169                 string newPath = string.Empty;
170                 try
171                 {
172                     if (!string.IsNullOrEmpty(tempUrlPath))
173                     {
174                         oldPath = Path.Combine(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(1), file.FileName);
175                         newPath = Path.Combine(CommonUnitity.SystemBinUrl + ConstFile.TEMPFOLDERNAME + tempUrlPath, file.FileName);
176                     }
177                     else
178                     {
179                         oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName);
180                         newPath = Path.Combine(CommonUnitity.SystemBinUrl + ConstFile.TEMPFOLDERNAME, file.FileName);
181                     }
182 
183                     //just deal with the problem which the files EndsWith xml can not download
184                     System.IO.FileInfo f = new FileInfo(newPath);
185                     if (!file.Size.ToString().Equals(f.Length.ToString()) && !file.FileName.ToString().EndsWith(".xml"))
186                     {
187                         ShowErrorAndRestartApplication();
188                     }                        
189                     
190                     //Added for dealing with the config file download errors
191                     string newfilepath = string.Empty;
192                     if (newPath.Substring(newPath.LastIndexOf(".") + 1).Equals(ConstFile.CONFIGFILEKEY))
193                     {
194                         if (System.IO.File.Exists(newPath))
195                         {
196                             if (newPath.EndsWith("_"))
197                             {
198                                 newfilepath = newPath;
199                                 newPath = newPath.Substring(0, newPath.Length - 1);
200                                 oldPath = oldPath.Substring(0, oldPath.Length - 1);
201                             }
202                             File.Move(newfilepath, newPath);
203                         }
204                     }
205                     //End added
206 
207                     if (File.Exists(oldPath))
208                     {
209                         MoveFolderToOld(oldPath, newPath);
210                     }
211                     else
212                     {
213                         //Edit for config_ file
214                         if (!string.IsNullOrEmpty(tempUrlPath))
215                         {
216                             if (!Directory.Exists(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(1)))
217                             {
218                                 Directory.CreateDirectory(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(1));
219 
220 
221                                 MoveFolderToOld(oldPath, newPath);
222                             }
223                             else
224                             {
225                                 MoveFolderToOld(oldPath, newPath);
226                             }
227                         }
228                         else
229                         {
230                             MoveFolderToOld(oldPath, newPath);
231                         }
232 
233                     }
234                 }
235                 catch (Exception exp)
236                 {
237                     //log the error message,you can use the application's log code
238                 }
239 
240             }
241 
242             //After dealed with all files, clear the data
243             this.allFileList.Clear();
244 
245             if (this.downloadFileList.Count == 0)
246                 Exit(true);
247             else
248                 Exit(false);
249 
250             evtDownload.Set();
251         }
252 
253         //To delete or move to old files
254         void MoveFolderToOld(string oldPath, string newPath)
255         {
256             if (File.Exists(oldPath + ".old"))
257                 File.Delete(oldPath + ".old");
258 
259             if (File.Exists(oldPath))
260                 File.Move(oldPath, oldPath + ".old");
261 
262 
263 
264             File.Move(newPath, oldPath);
265             //File.Delete(oldPath + ".old");
266         }
267 
268         delegate void ShowCurrentDownloadFileNameCallBack(string name);
269         private void ShowCurrentDownloadFileName(string name)
270         {
271             if (this.labelCurrentItem.InvokeRequired)
272             {
273                 ShowCurrentDownloadFileNameCallBack cb = new ShowCurrentDownloadFileNameCallBack(ShowCurrentDownloadFileName);
274                 this.Invoke(cb, new object[] { name });
275             }
276             else
277             {
278                 this.labelCurrentItem.Text = name;
279             }
280         }
281 
282         delegate void SetProcessBarCallBack(int current, int total);
283         private void SetProcessBar(int current, int total)
284         {
285             if (this.progressBarCurrent.InvokeRequired)
286             {
287                 SetProcessBarCallBack cb = new SetProcessBarCallBack(SetProcessBar);
288                 this.Invoke(cb, new object[] { current, total });
289             }
290             else
291             {
292                 this.progressBarCurrent.Value = current;
293                 this.progressBarTotal.Value = total;
294             }
295         }
296 
297         delegate void ExitCallBack(bool success);
298         private void Exit(bool success)
299         {
300             if (this.InvokeRequired)
301             {
302                 ExitCallBack cb = new ExitCallBack(Exit);
303                 this.Invoke(cb, new object[] { success });
304             }
305             else
306             {
307                 this.isFinished = success;
308                 this.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
309                 this.Close();
310             }
311         }
312 
313         private void OnCancel(object sender, EventArgs e)
314         {
315             //bCancel = true;
316             //evtDownload.Set();
317             //evtPerDonwload.Set();
318             ShowErrorAndRestartApplication();
319         }
320 
321         private void DealWithDownloadErrors()
322         {
323             try
324             {
325                 //Test Network is OK or not.
326                 Config config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME));
327                 WebClient client = new WebClient();
328                 client.DownloadString(config.ServerUrl);
329             }
330             catch (Exception)
331             {
332                 //log the error message,you can use the application's log code
333                 ShowErrorAndRestartApplication();
334             }
335         }
336 
337         private void ShowErrorAndRestartApplication()
338         {
339             MessageBox.Show(ConstFile.NOTNETWORK,ConstFile.MESSAGETITLE, MessageBoxButtons.OK, MessageBoxIcon.Information);
340             CommonUnitity.RestartApplication();
341         }
342 
343         #endregion
344     }
View Code

以上就是整体的自动更新程序核心代码。

下面是创建xml的程序代码:

代码是根据评论修改的如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.Xml;
 10 using System.IO;
 11 using System.Diagnostics;
 12 
 13 namespace CreateXmlTools
 14 {
 15     public partial class FormMain : Form
 16     {
 17         public FormMain()
 18         {
 19             InitializeComponent();
 20             txtWebUrl.Text = "172.30.100.55:8011";
 21             txtWebUrl.ForeColor = Color.Gray;
 22         }
 23 
 24         //获取当前目录
 25         //string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
 26         string currentDirectory = System.Environment.CurrentDirectory;
 27         //服务端xml文件名称
 28         string serverXmlName = "AutoupdateService.xml";
 29         //更新文件URL前缀
 30         string url = string.Empty;
 31 
 32         void CreateXml()
 33         {
 34             //创建文档对象
 35             XmlDocument doc = new XmlDocument();
 36             //创建根节点
 37             XmlElement root = doc.CreateElement("updateFiles");
 38             //头声明
 39             XmlDeclaration xmldecl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
 40             doc.AppendChild(xmldecl);
 41             DirectoryInfo dicInfo = new DirectoryInfo(currentDirectory);
 42             
 43             //调用递归方法组装xml文件
 44             PopuAllDirectory(doc, root, dicInfo);
 45             //追加节点
 46             doc.AppendChild(root);
 47             //保存文档
 48             doc.Save(serverXmlName);
 49         }
 50 
 51         //递归组装xml文件方法
 52         private void PopuAllDirectory(XmlDocument doc, XmlElement root, DirectoryInfo dicInfo)
 53         {
 54             foreach (FileInfo f in dicInfo.GetFiles())
 55             {
 56                 //排除当前目录中生成xml文件的工具文件
 57                 if (f.Name != "CreateXmlTools.exe" && f.Name != "AutoupdateService.xml")
 58                 {
 59                     string path = dicInfo.FullName.Replace(currentDirectory, "").Replace("\\", "/");
 60                     string folderPath=string.Empty;
 61                     if (path != string.Empty)
 62                     {
 63                         folderPath = path.TrimStart('/') + "/";
 64                     }
 65                     XmlElement child = doc.CreateElement("file");
 66                     child.SetAttribute("path", folderPath + f.Name);
 67                     child.SetAttribute("url", url + path + "/" + f.Name);
 68                     child.SetAttribute("lastver", FileVersionInfo.GetVersionInfo(f.FullName).FileVersion);
 69                     child.SetAttribute("size", f.Length.ToString());
 70                     child.SetAttribute("needRestart", "false");
 71                     child.SetAttribute("version", Guid.NewGuid().ToString());
 72                     root.AppendChild(child);
 73                 }
 74             }
 75 
 76             foreach (DirectoryInfo di in dicInfo.GetDirectories())
 77                 PopuAllDirectory(doc, root, di);
 78         }
 79 
 80         private void btnCreate_Click(object sender, EventArgs e)
 81         {
 82             url = "http://" + txtWebUrl.Text.Trim();
 83             CreateXml();
 84             ReadXml();
 85         }
 86 
 87         private void ReadXml()
 88         {
 89             string path="AutoupdateService.xml";
 90             rtbXml.ReadOnly = true;
 91             if (File.Exists(path))
 92             {
 93                 rtbXml.Text = File.ReadAllText(path);
 94             }
 95         }
 96 
 97         private void txtWebUrl_Enter(object sender, EventArgs e)
 98         {
 99             txtWebUrl.ForeColor = Color.Black;
100             if (txtWebUrl.Text.Trim() == "172.30.100.55:8011")
101             {
102                 txtWebUrl.Text = string.Empty;
103             }
104         }
105         
106     }
107 }
View Code

由于我的主程序是被别人写死的(没有修改权限没有代码)所以我只能单独写更新程序,由用户打开我的更新程序调用exe的方式来处理

所以多了一个程序专门用来更新的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AutoUpdater;
using System.Net;
using System.Xml;
using KnightsWarriorAutoupdater;

namespace KnightsWarrior
{
    public partial class UpdateForm : Form
    {
        public UpdateForm()
        {
            InitializeComponent();
            InitCheckUpdate();
        }
        void InitCheckUpdate()
        {
            #region check and download new version program
            bool bHasError = false;
            IAutoUpdater autoUpdater = new KnightsWarriorAutoupdater.AutoUpdater();
            try
            {
                autoUpdater.Update();
            }
            catch (WebException exp)
            {
                MessageBox.Show("服务器连接失败");
                bHasError = true;
            }
            catch (XmlException exp)
            {
                bHasError = true;
                MessageBox.Show("下载更新文件错误");
            }
            catch (NotSupportedException exp)
            {
                bHasError = true;
                MessageBox.Show("升级文件配置错误");
            }
            catch (ArgumentException exp)
            {
                bHasError = true;
                MessageBox.Show("下载升级文件错误");
            }
            catch (Exception exp)
            {
                bHasError = true;
                MessageBox.Show("更新过程中出现错误");
            }
            finally
            {
                if (bHasError == true)
                {
                    try
                    {
                        autoUpdater.RollBack();
                    }
                    catch (Exception)
                    {
                        //Log the message to your file or database
                    }
                }
                OperProcess op = new OperProcess();
                //启动进程
                op.StartProcess();
            }
            #endregion
        }
    }
}        

1、服务器端

  1、CreateXmlTools.exe给发布dll人员使用,用来生成要升级文件的列表,放在更新文件中的。
  2、webServer地址是web服务器的地址。
  3、点击生成之后会生成一个文件名为AutoupdateService.xml文件。
  4、将生成的xml文件放置在web服务器的根目录里。
2、客户端
  1、AutoUpdater.Config,该文件是保证客户端更新程序调用获取更新文件列表时使用的。
  2、KnightsWarrior.exe更新主程序,用户直接调用该文件
  3、AutoUpdater.dll更新程序的核心程序

本程序是要结合web服务器使用的,所有要更新的文件需要放在搭建的web服务器上,按照对应的目录存放,点CreateXmlTools.exe会生成一个xml文件的。

以上就是所有修改和增加部分的程序的代码及一些简要说明。建议先去看看组件源码,圣殿骑士大哥将其托管在托管地址。欢迎拍砖!

具体的使用方式和强制更新的代码在:Winform(C#.NET)自动更新组件的使用及部分功能实现(续),Demo也在这里。

posted @ 2013-11-28 13:29  逆水寒龙  阅读(26366)  评论(39编辑  收藏  举报