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 }
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 }
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 }
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 }
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 }
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 }
以上就是整体的自动更新程序核心代码。
下面是创建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 }
由于我的主程序是被别人写死的(没有修改权限没有代码)所以我只能单独写更新程序,由用户打开我的更新程序调用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也在这里。
-------------------------------------------------
保持专注,只做一件事,做好这件事!@
-------------------------------------------------