UpdateClass.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. using ProjectBase.Data.Logs;
  2. using ProjectBase.Data.Zip;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Net;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12. using System.Xml;
  13. using System.Xml.Serialization;
  14. namespace ProjectBase.Data.Update
  15. {
  16. /// <summary>
  17. /// 程序更新事件参数
  18. /// </summary>
  19. public class ManifestEventArgs : EventArgs
  20. {
  21. public Manifest Manifest { get; set; }
  22. }
  23. /// <summary>
  24. /// 激活安装开始事件参数
  25. /// </summary>
  26. public class ActivationStartedEventArgs : EventArgs
  27. {
  28. public Manifest Manifest { get; set; }
  29. public bool Cancel { get; set; }
  30. }
  31. /// <summary>
  32. /// 安装完成事件参数
  33. /// </summary>
  34. public class ActivationCompletedEventArgs : AsyncCompletedEventArgs
  35. {
  36. public ActivationCompletedEventArgs(Exception error, bool cancelled, object userState)
  37. : base(error, cancelled, userState)
  38. {
  39. }
  40. public Manifest Manifest { get; set; }
  41. }
  42. /// <summary>
  43. /// 程序自动更新操作类,封装了文件下载、文件复制、文件解压等操作
  44. /// </summary>
  45. public class UpdateClass
  46. {
  47. #region 变量属性
  48. private DownloadClass downloader = new DownloadClass();
  49. private FileCopyClass fileCopyer = new FileCopyClass();
  50. private UpdaterConfigurationView updateCfgView = new UpdaterConfigurationView();
  51. private string backupFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../backup");
  52. /// <summary>
  53. /// 封装的文件下载操作类
  54. /// </summary>
  55. public DownloadClass Downloader
  56. {
  57. get
  58. {
  59. return downloader;
  60. }
  61. }
  62. /// <summary>
  63. /// 封装的文件复制操作类
  64. /// </summary>
  65. public FileCopyClass FileCopyer
  66. {
  67. get
  68. {
  69. return fileCopyer;
  70. }
  71. }
  72. #endregion
  73. #region 事件
  74. /// <summary>
  75. /// 下载进度
  76. /// </summary>
  77. public event EventHandler<DownloadProgressEventArgs> DownloadProgressChanged;
  78. /// <summary>
  79. /// 下载完成事件
  80. /// </summary>
  81. public event EventHandler<DownloadCompleteEventArgs> DownloadCompleted;
  82. /// <summary>
  83. /// 下载错误触发的事件
  84. /// </summary>
  85. public event EventHandler<DownloadErrorEventArgs> DownloadError;
  86. public event EventHandler<ManifestEventArgs> ActivationInitializing;
  87. public event EventHandler<ActivationCompletedEventArgs> ActivationCompleted;
  88. public event EventHandler<ActivationStartedEventArgs> ActivationStarted;
  89. public event EventHandler<FileCopyProgressChangedEventArgs> ActivationProgressChanged;
  90. public event EventHandler<FileCopyErrorEventArgs> ActivationError;
  91. #endregion
  92. #region 下载更新实现
  93. public UpdateClass()
  94. {
  95. downloader.DownloadCompleted += new EventHandler<DownloadCompleteEventArgs>(downloader_DownloadCompleted);
  96. downloader.DownloadError += new EventHandler<DownloadErrorEventArgs>(downloader_DownloadError);
  97. downloader.DownloadProgressChanged += new EventHandler<DownloadProgressEventArgs>(downloader_DownloadProgressChanged);
  98. fileCopyer.FileCopyError += new EventHandler<FileCopyErrorEventArgs>(fileCopyer_FileCopyError);
  99. fileCopyer.FileCopyCompleted += new EventHandler<FileCopyCompletedEventArgs>(fileCopyer_FileCopyCompleted);
  100. fileCopyer.FileCopyProgressChanged += new EventHandler<FileCopyProgressChangedEventArgs>(fileCopyer_FileCopyProgressChanged);
  101. }
  102. /// <summary>
  103. /// 是否有最新的版本
  104. /// </summary>
  105. public bool HasNewVersion
  106. {
  107. get
  108. {
  109. var m = CheckForUpdates();
  110. return m.Length > 0;
  111. }
  112. }
  113. /// <summary>
  114. /// 检查更新,返回更新清单列表
  115. /// </summary>
  116. /// <returns></returns>
  117. public Manifest[] CheckForUpdates()
  118. {
  119. updateCfgView.Refresh();
  120. Uri uri = new Uri(updateCfgView.ManifestUri);
  121. string doc = DownLoadFile(uri, updateCfgView.ManifestName, updateCfgView.ManifestPasswd);
  122. XmlSerializer xser = new XmlSerializer(typeof(Manifest));
  123. var manifest = xser.Deserialize(new XmlTextReader(doc, XmlNodeType.Document, null)) as Manifest;
  124. if (manifest == null ||
  125. manifest.Version == updateCfgView.Version ||
  126. manifest.MyApplication.ApplicationId != updateCfgView.ApplicationId)
  127. {
  128. return new Manifest[0];
  129. }
  130. return new Manifest[] { manifest };
  131. }
  132. /// <summary>
  133. /// 用于远程下载文件清单
  134. /// </summary>
  135. /// <param name="uri">文件清单网络路径</param>
  136. /// <returns></returns>
  137. private string DownLoadFile(Uri uri, string username, string password)
  138. {
  139. WebRequest request = WebRequest.Create(uri);
  140. request.Credentials = new NetworkCredential(username, password);
  141. string response = String.Empty;
  142. using (WebResponse res = request.GetResponse())
  143. {
  144. using (StreamReader reader = new StreamReader(res.GetResponseStream(), true))
  145. {
  146. response = reader.ReadToEnd();
  147. }
  148. }
  149. return response;
  150. }
  151. /// <summary>
  152. /// 同步下载文件清单中的文件
  153. /// </summary>
  154. /// <param name="manifests">下载文件清单</param>
  155. public void Download(Manifest[] manifests)
  156. {
  157. foreach (var m in manifests)
  158. {
  159. downloader.Download(m);
  160. }
  161. }
  162. /// <summary>
  163. /// 异步下载文件清单中的文件
  164. /// </summary>
  165. /// <param name="manifests">下载文件清单</param>
  166. public void DownloadAsync(Manifest[] manifests)
  167. {
  168. foreach (var m in manifests)
  169. {
  170. downloader.DownloadAsync(m);
  171. }
  172. }
  173. /// <summary>
  174. /// 下载完毕后执行的启动操作
  175. /// </summary>
  176. /// <param name="manifests"></param>
  177. public void Activate(Manifest[] manifests)
  178. {
  179. foreach (var m in manifests)
  180. {
  181. OnActivationInitializing(new ManifestEventArgs() { Manifest = m });
  182. Backup(m, downloader.TempPath);
  183. ActivationStartedEventArgs e = new ActivationStartedEventArgs() { Manifest = m };
  184. OnActivationStarted(e);
  185. if (e.Cancel)
  186. {
  187. Clear();
  188. break;
  189. }
  190. else
  191. {
  192. fileCopyer.CopyAsync(m, downloader.TempPath);
  193. }
  194. }
  195. }
  196. /// <summary>
  197. /// 备份操作
  198. /// </summary>
  199. /// <param name="manifest">文件清单</param>
  200. private void Backup(Manifest manifest, string sourcePath)
  201. {
  202. try
  203. {
  204. //string sourcePath = Path.GetFullPath(manifest.MyApplication.Location);
  205. string s_filename = string.Empty;
  206. string t_filename = string.Empty;
  207. if (!Directory.Exists(backupFilePath))
  208. {
  209. Directory.CreateDirectory(backupFilePath);
  210. }
  211. foreach (var file in manifest.ManifestFiles.Files)
  212. {
  213. t_filename = Path.Combine(backupFilePath, file.Source);
  214. s_filename = Path.Combine(sourcePath, file.Source);
  215. if (File.Exists(s_filename))
  216. {
  217. File.Copy(s_filename, t_filename, true);
  218. }
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. LogHelper.log.Error("备份文件出现错误" + ex);
  224. }
  225. }
  226. /// <summary>
  227. /// 回滚文件下载内容
  228. /// </summary>
  229. /// <param name="manifest"></param>
  230. public void Rollback(Manifest manifest)
  231. {
  232. try
  233. {
  234. string filename = string.Empty;
  235. foreach (var file in manifest.ManifestFiles.Files)
  236. {
  237. filename = Path.Combine(backupFilePath, file.Source);
  238. File.Copy(filename, Path.Combine(Path.GetFullPath(manifest.MyApplication.Location), file.Source));
  239. }
  240. //Directory.Delete(backupFilePath, true);
  241. }
  242. catch (Exception ex)
  243. {
  244. LogHelper.log.Error("回滚文件出现错误" + ex);
  245. }
  246. }
  247. /// <summary>
  248. /// 清除临时文件
  249. /// </summary>
  250. private void Clear()
  251. {
  252. try
  253. {
  254. //Directory.Delete(backupFilePath, true);
  255. Directory.Delete(downloader.TempPath, true);
  256. }
  257. catch (Exception ex)
  258. {
  259. LogHelper.log.Error("清理临时文件出现错误" + ex);
  260. }
  261. }
  262. #endregion
  263. #region 事件处理
  264. private void fileCopyer_FileCopyError(object sender, FileCopyErrorEventArgs e)
  265. {
  266. OnActivationError(e);
  267. }
  268. private void fileCopyer_FileCopyProgressChanged(object sender, FileCopyProgressChangedEventArgs e)
  269. {
  270. if (ActivationProgressChanged != null)
  271. {
  272. ActivationProgressChanged(sender, e);
  273. }
  274. }
  275. private void fileCopyer_FileCopyCompleted(object sender, FileCopyCompletedEventArgs e)
  276. {
  277. Clear();
  278. try
  279. {
  280. //BackupSourceFiles(e.Manifest, updateCfgView.Version);
  281. updateCfgView.Version = e.Manifest.Version;
  282. }
  283. catch (Exception ex)
  284. {
  285. LogHelper.log.Info("备份原始程序出错误, 错误为." + ex);
  286. }
  287. if (ActivationCompleted != null)
  288. {
  289. ActivationCompletedEventArgs evt = new ActivationCompletedEventArgs(e.Error, e.Cancelled, e.UserState);
  290. evt.Manifest = e.Manifest;
  291. OnActivationCompleted(evt);
  292. }
  293. }
  294. /// <summary>
  295. /// 打包备份原始版本程序
  296. /// </summary>
  297. /// <param name="Manifest"></param>
  298. private void BackupSourceFiles(Manifest manifest, string sourceVersion)
  299. {
  300. string folderFullName = new DirectoryInfo("../").FullName;//当前应用程序路径的上级目录 "../" + rootPath;
  301. DirectoryInfo TheFolder = new DirectoryInfo(folderFullName);
  302. foreach (DirectoryInfo NextFolder in TheFolder.GetDirectories())
  303. {
  304. if (NextFolder.Name == manifest.MyApplication.Expand)
  305. {
  306. string sourceFiles = folderFullName + NextFolder.Name;
  307. string targetFiles = backupFilePath + "/" + NextFolder.Name + "_" + sourceVersion + ".zip";
  308. ZipUtility.ZipFiles(sourceFiles, targetFiles, null);
  309. }
  310. }
  311. }
  312. private void downloader_DownloadProgressChanged(object sender, DownloadProgressEventArgs e)
  313. {
  314. if (DownloadProgressChanged != null)
  315. {
  316. DownloadProgressChanged(sender, e);
  317. }
  318. }
  319. private void downloader_DownloadError(object sender, DownloadErrorEventArgs e)
  320. {
  321. if (DownloadError != null)
  322. {
  323. DownloadError(sender, e);
  324. }
  325. }
  326. private void downloader_DownloadCompleted(object sender, DownloadCompleteEventArgs e)
  327. {
  328. if (DownloadCompleted != null)
  329. {
  330. DownloadCompleted(sender, e);
  331. }
  332. }
  333. private void OnActivationInitializing(ManifestEventArgs e)
  334. {
  335. if (ActivationInitializing != null)
  336. {
  337. ActivationInitializing(this, e);
  338. }
  339. }
  340. private void OnActivationStarted(ActivationStartedEventArgs e)
  341. {
  342. if (ActivationStarted != null)
  343. {
  344. ActivationStarted(this, e);
  345. }
  346. }
  347. private void OnActivationCompleted(ActivationCompletedEventArgs e)
  348. {
  349. if (ActivationCompleted != null)
  350. {
  351. ActivationCompleted(this, e);
  352. }
  353. }
  354. private void OnActivationError(FileCopyErrorEventArgs e)
  355. {
  356. if (ActivationError != null)
  357. {
  358. ActivationError(this, e);
  359. }
  360. }
  361. private void OnActivationProgressChanged(FileCopyProgressChangedEventArgs e)
  362. {
  363. if (ActivationProgressChanged != null)
  364. {
  365. ActivationProgressChanged(this, e);
  366. }
  367. }
  368. #endregion
  369. }
  370. }