Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Bugfix: /? help now works. Enhanced: when the /verbose flag is specified, show the full stack track for exceptions. Refactor: increased code readability by not using `var` when it's not apparent at first glance what the type is going to be. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | develop |
Files: | files | file ages | folders |
SHA1: |
b80ceff46759d458b40d4dbcf2b86d36 |
User & Date: | tinus 2018-05-31 05:59:46.848 |
Context
2018-06-28
| ||
19:57 | Small code optimizations. check-in: 3bd88a0184 user: tinus tags: develop | |
2018-05-31
| ||
05:59 | Bugfix: /? help now works. Enhanced: when the /verbose flag is specified, show the full stack track for exceptions. Refactor: increased code readability by not using `var` when it's not apparent at first glance what the type is going to be. check-in: b80ceff467 user: tinus tags: develop | |
2018-03-23
| ||
21:16 | Implemented command-line help. check-in: 41b3d45087 user: tinus tags: develop | |
Changes
Changes to ZTUpdater/Program.cs.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 | namespace ZTUpdater { class Program { [STAThread] static int Main(string[] args) { try { // Read the command-line options | > < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | namespace ZTUpdater { class Program { [STAThread] static int Main(string[] args) { var MinimumLevel = TraceLevel.Info; try { // Read the command-line options string OptName = null; var Options = new Dictionary<string, string>(); var Arguments = new List<string>(); foreach (var arg in args) { if (OptName != null) { |
︙ | ︙ | |||
58 59 60 61 62 63 64 | var Dialog = new System.Windows.Forms.FolderBrowserDialog { SelectedPath = @"C:\ZTree", ShowNewFolderButton = false, Description = "Please select the folder where ZTreeWin is installed" }; if (Dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) | | | | > > > > > > > > | < < < < | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | var Dialog = new System.Windows.Forms.FolderBrowserDialog { SelectedPath = @"C:\ZTree", ShowNewFolderButton = false, Description = "Please select the folder where ZTreeWin is installed" }; if (Dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) Updater.ZTreeHome = Dialog.SelectedPath; } if (Options.TryGetValue("archive", out var Value)) Updater.ArchiveDir = new DirectoryInfo(Value); else if (Options.TryGetValue("backup", out Value)) Updater.BackupDir = new DirectoryInfo(Value); // Perform the actual update int FilesUpdated; if (Arguments.Count > 0) { FilesUpdated = Updater.UpdateFromFile(Arguments[0]); } else { var UpdateTask = Updater.UpdateAsync(); UpdateTask.Wait(); FilesUpdated = UpdateTask.Result; } WriteLog($"{FilesUpdated} files updated.", TraceLevel.Info); return FilesUpdated > 0 ? 0 : 1; } catch (Exception ex) { Func<Exception,bool> WriteException = (iex) => { if (MinimumLevel >= TraceLevel.Verbose) Console.Error.WriteLine(iex.ToString()); else Console.Error.WriteLine(iex.Message); return true; }; var BackupColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Magenta; if (ex is AggregateException) ((AggregateException)ex).Handle(WriteException); else WriteException(ex); Console.ForegroundColor = BackupColor; return 255; } } private static void ShowHelp() { string Name = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location); var Lines = new List<string> { $@"{Name} [/v | /verbose] [/home ZTHOMEDIR] [/backup BACKUPDIR] [/archive ARCHIVEDIR] [UPDATEZIPFILE]", "", $@"/verbose Display more messages.", $@"/home ZTHOMEDIR ZTreeWin's installation directory. If not specified, {Name} attempts to determine it automatically. Failing that, it must be browsed interactively.", $@"/backup BACKUPDIR Where to save backups of files replaced during an update. Default is %#ZTHome%\Backup.", |
︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 154 155 156 157 158 | } else { // TODO: break on word boundaries, and omit spaces at the start of a new line? Console.Write(Description.Extract(0, Console.BufferWidth - TabPos)); while (Description.Length > 0) { Console.Write(Prefix); Console.Write(Description.Extract(0, Console.BufferWidth - TabPos)); } Console.WriteLine(); } } } | > | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | } else { // TODO: break on word boundaries, and omit spaces at the start of a new line? Console.Write(Description.Extract(0, Console.BufferWidth - TabPos)); while (Description.Length > 0) { Console.WriteLine(); Console.Write(Prefix); Console.Write(Description.Extract(0, Console.BufferWidth - TabPos)); } Console.WriteLine(); } } } |
︙ | ︙ | |||
175 176 177 178 179 180 181 | { if (_levelColors.Count == 0) { _levelColors.Add(TraceLevel.Verbose, ConsoleColor.DarkGray); _levelColors.Add(TraceLevel.Warning, ConsoleColor.Yellow); _levelColors.Add(TraceLevel.Error, ConsoleColor.Red); } | | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | { if (_levelColors.Count == 0) { _levelColors.Add(TraceLevel.Verbose, ConsoleColor.DarkGray); _levelColors.Add(TraceLevel.Warning, ConsoleColor.Yellow); _levelColors.Add(TraceLevel.Error, ConsoleColor.Red); } var Output = level >= TraceLevel.Warning ? Console.Out : Console.Error; var BackupColor = Console.ForegroundColor; if (_levelColors.TryGetValue(level, out var Color)) Console.ForegroundColor = Color; Output.WriteLine(message); Console.ForegroundColor = BackupColor; } |
︙ | ︙ |
Changes to ZTUpdater/ZTUpdater.cs.
︙ | ︙ | |||
37 38 39 40 41 42 43 | { get => _ZTreeHome; set { _ZTreeHome = value; if (_ZTreeHome != null) { | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | { get => _ZTreeHome; set { _ZTreeHome = value; if (_ZTreeHome != null) { string[] Executables = Directory.GetFiles(ZTreeHome, Executable); if (Executables.Length > 0) Executable = Executables[0]; else Executable = Path.Combine(ZTreeHome, Executable); // determine version of local executable CurrentVersion = FileVersionInfo.GetVersionInfo(Executable).FileVersion; |
︙ | ︙ | |||
79 80 81 82 83 84 85 | // from the environment string ZTHome = Environment.GetEnvironmentVariable("#ZTHome"); if (Directory.Exists(ZTHome)) return ZTHome; // from registry (both Win32 and Win64) | | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | // from the environment string ZTHome = Environment.GetEnvironmentVariable("#ZTHome"); if (Directory.Exists(ZTHome)) return ZTHome; // from registry (both Win32 and Win64) object InstallDir = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\ZTreeWin", "Install_Dir", null); if (InstallDir is string && Directory.Exists(ZTHome = (string)InstallDir)) return ZTHome; InstallDir = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ZTreeWin", "Install_Dir", null); if (InstallDir is string && Directory.Exists(ZTHome = (string)InstallDir)) return ZTHome; return null; } private Regex _rexZetaAvailable = new Regex(@"forum_entry.php\?id=(\d+)""[^\<]*?v(\d+\.\S+) Now Available", RegexOptions.Compiled | RegexOptions.IgnoreCase); private Regex _rexWhatsNew = new Regex(@"<div class=""posting"">(.*?)</div><p class=""signature"">", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); private Regex _rexLink = new Regex(@"""(https?://(www.)?z(edtek|tree).com\/[^""]*\.(zip|exe))""", RegexOptions.Compiled | RegexOptions.IgnoreCase); public async Task<Uri> GetUriLatestVersion() { using (var Client = new HttpClient()) { // get the forum home page Log("Looking for announcement on ZTreeWin Forum..."); |
︙ | ︙ | |||
164 165 166 167 168 169 170 | /// <summary> /// Checks for an updated version of ZTreeWin; and if found, download and install it. /// </summary> /// <returns>The number of files that were updated.</returns> public async Task<int> UpdateAsync() { | | | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | /// <summary> /// Checks for an updated version of ZTreeWin; and if found, download and install it. /// </summary> /// <returns>The number of files that were updated.</returns> public async Task<int> UpdateAsync() { Log($@"ZTreeWin version {CurrentVersion} located in ""{ZTreeHome}"".", TraceLevel.Info); if (!Directory.Exists(ZTreeHome)) throw new DirectoryNotFoundException($@"Directory ""{ZTreeHome}"" not found"); Uri DownloadUri = await GetUriLatestVersion(); if (DownloadUri == null) return 0; // Prepare to save the file in the user’s Downloads folder string Folder = (ArchiveDir ?? BackupDir)?.FullName ?? KnownFolders.Downloads.Path; string OrgZipFile = DownloadUri.AbsolutePath; int Pos = OrgZipFile.LastIndexOf("/"); |
︙ | ︙ | |||
193 194 195 196 197 198 199 | Counter++; ZipFile = Base + $" ({Counter})" + Extension; } Log($@"Downloading update file to ""{OrgZipFile}""..."); using (var Client = new HttpClient()) { | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | Counter++; ZipFile = Base + $" ({Counter})" + Extension; } Log($@"Downloading update file to ""{OrgZipFile}""..."); using (var Client = new HttpClient()) { Stream ZipStream = await Client.GetStreamAsync(DownloadUri); using (var FileStream = new FileStream(ZipFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read)) { await ZipStream.CopyToAsync(FileStream); } } // If the newly downloaded file is identical to the existing one, delete the new one and just reuse the old one. |
︙ | ︙ | |||
248 249 250 251 252 253 254 | } // Try moving to version-based folder first; only if that doesn't work, try to rename // to a version-based file name in the same folder. Log($"\t{Entry.FullName}\tbacking up existing file."); try { | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | } // Try moving to version-based folder first; only if that doesn't work, try to rename // to a version-based file name in the same folder. Log($"\t{Entry.FullName}\tbacking up existing file."); try { string BackupName = VersionBasedFolder(TargetFile); try { File.Move(TargetFile.FullName, BackupName); TargetFile.Refresh(); if (TargetFile.Exists) // Then, the move was NOT successful throw new Exception("Unable to move the file."); |
︙ | ︙ | |||
281 282 283 284 285 286 287 | } return NumFiles; } private string VersionBasedFolder(FileInfo File) { var SourceDir = new DirectoryInfo(ZTreeHome); | | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | } return NumFiles; } private string VersionBasedFolder(FileInfo File) { var SourceDir = new DirectoryInfo(ZTreeHome); var TargetDir = BackupDir ?? SourceDir.CreateSubdirectory("Backup"); TargetDir = TargetDir.CreateSubdirectory(CurrentVersion); return Path.Combine(TargetDir.FullName, File.FullName.Substring(SourceDir.FullName.Length + 1)); } private string VersionBasedFilename(FileInfo File) { var Extension = File.Extension; |
︙ | ︙ | |||
347 348 349 350 351 352 353 | // decode all HTML entities var rexEntity = new Regex(@"&(#x?[0-9a-f]{1,4}|\w{2,8});", RegexOptions.Compiled | RegexOptions.IgnoreCase); Match Match; int StartAt = 0; while ((Match = rexEntity.Match(Text, StartAt)).Success) { | | | | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | // decode all HTML entities var rexEntity = new Regex(@"&(#x?[0-9a-f]{1,4}|\w{2,8});", RegexOptions.Compiled | RegexOptions.IgnoreCase); Match Match; int StartAt = 0; while ((Match = rexEntity.Match(Text, StartAt)).Success) { string Entity = Match.Groups[1].Value; string Replacement = "?"; if (Entity.StartsWith("#")) { int CharCode = 0; if (Entity.Substring(1, 1) == "x") // hexadecimal char code CharCode = int.Parse(Entity.Substring(2), System.Globalization.NumberStyles.HexNumber); else |
︙ | ︙ |