• 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也在这里。

  • 相关阅读:
    使用pyppeteer 下载chromium 报错 或速度慢
    Splash抓取jd
    Splash抓取javaScript动态渲染页面
    Django3+websocket+paramiko实现web页面实时输出
    django3 websockets
    MySQL数据库OLTP基准测试( sysbench)
    数据库链接池大小设置和相关测试
    Linux 性能调优IO篇:工具命令篇
    Linux 性能调优内存篇:工具命令篇
    Vue笔记:vue项目引入bootstrap、elementUI、echarts
  • 原文地址:https://www.cnblogs.com/24la/p/autoupdater-component.html
Copyright © 2020-2023  润新知