/// <summary> /// Update the current application /// </summary> public static void PerformUpdate(Options options, ColorScheme colorScheme) { try { // download the update // replace the current exe // relaunch var filename = Path.Combine(Path.GetTempPath(), "NUnit.Commander\\NUnit.Commander.msi"); Directory.CreateDirectory(Path.GetDirectoryName(filename)); // this won't work with .net core single file publishing //var assemblyFile = Assembly.GetExecutingAssembly().Location; var currentProcess = Process.GetCurrentProcess(); var assemblyFile = currentProcess.MainModule.FileName; #if DEBUG var assemblyArgs = Environment.CommandLine.Replace(assemblyFile.Replace(".exe", ".dll"), ""); #else var assemblyArgs = Environment.CommandLine.Replace(assemblyFile, ""); #endif var assemblyPath = Path.GetDirectoryName(assemblyFile); var assemblyTempFile = $"{assemblyFile}.tmp"; var client = new HttpClient(); var percentageX = 0; if (!Console.IsOutputRedirected) { Console.CursorVisible = false; Console.Write($"Downloading v{LatestVersion.ToString()} update... "); percentageX = Console.CursorLeft; } Task.Run(async() => { var response = await client.GetAsync($"https://github.com/replaysMike/NUnit.Commander/releases/latest/download/NUnit.Commander.msi", HttpCompletionOption.ResponseHeadersRead); var stream = await response.Content.ReadAsStreamAsync(); var totalLength = response.Content.Headers.ContentLength; var buffer = new byte[512 * 1024]; // 512kb buffer int bytesRead; var streamWriter = new FileStream(filename, FileMode.Create); do { bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length); streamWriter.Write(buffer, 0, bytesRead); var percDone = ((double)streamWriter.Length / totalLength) * 100.0; if (!Console.IsOutputRedirected) { Console.SetCursorPosition(percentageX, Console.CursorTop); Console.Write($"{percDone:n0}% ", colorScheme.Duration); } } while (bytesRead > 0); streamWriter.Close(); streamWriter.Dispose(); if (!Console.IsOutputRedirected) { Console.WriteLine($"{Environment.NewLine}Download complete. ", colorScheme.Duration); } }).GetAwaiter().GetResult(); if (!Console.IsOutputRedirected) { Console.Write($"Installing v{LatestVersion.ToString()} update ({assemblyPath})... "); } // rename the current assembly if (File.Exists(assemblyTempFile)) { File.Delete(assemblyTempFile); } File.Move(assemblyFile, assemblyTempFile); var process = new Process(); process.StartInfo.FileName = "msiexec"; process.StartInfo.WorkingDirectory = Path.GetTempPath(); process.StartInfo.Arguments = $"/passive /norestart /i {filename} INSTALLFOLDER={assemblyPath}"; // To enable msi installation logging use: /log c:\\logs\\commander-msi-install.log process.StartInfo.Verb = "runas"; process.Start(); //var exited = process.WaitForExit(30 * 1000); if (!Console.IsOutputRedirected) { Console.WriteLine($"done!"); if (options.Relaunch) { // relaunch application with same arguments. Note this will be out of process try { var relaunchProcess = new Process(); relaunchProcess.StartInfo.FileName = assemblyFile; relaunchProcess.StartInfo.Arguments = assemblyArgs; relaunchProcess.Start(); } catch (Exception ex) { Console.WriteLine($"Failed to restart application automatically. Please re-launch application manually. Error: {ex.Message}"); } } // start a new process with a slight delay to cleanup our temp assembly file Process.Start(new ProcessStartInfo() { Arguments = "/C choice /C Y /N /D Y /T 2 & Del \"" + assemblyTempFile + "\"", WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, FileName = "cmd.exe" }); // return success updated Environment.Exit((int)ExitCode.ApplicationUpdated); } } catch (Exception ex) { Console.WriteLine($"Failed to update application. {ex.Message}"); // continue with run } }
static void DisplayInitializationScreen(Options options, ApplicationConfiguration config, ColorScheme colorScheme, RunContext runContext) { // initialize the performance counters before launching the test runner // this is because it can be slow, we don't want to delay connecting to the test runner try { if (!Console.IsOutputRedirected) { var currentFont = ConsoleUtil.GetCurrentFont().FontName; Console.Write($"Console font: "); Console.WriteLine(currentFont, colorScheme.DarkDefault); var unicodeTestHeader = "Unicode test:"; Console.Write(unicodeTestHeader); Console.WriteLine("\u2022 ╭╮╰╯═══\u2801\u2802\u2804\u2840\u28FF", colorScheme.DarkDefault); var conEmuDetected = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ConEmuPID")); var parentProcess = ParentProcessUtilities.GetParentProcess(); var powershellDetected = parentProcess?.ProcessName.Equals("powershell", StringComparison.InvariantCultureIgnoreCase) == true; var dotChar = ConsoleUtil.GetCharAt(unicodeTestHeader.Length, Console.CursorTop); // dot ok var brailleChar = ConsoleUtil.GetCharAt(unicodeTestHeader.Length + 9, Console.CursorTop); // braille ok var dotCharOk = false; if (OperatingSystem.IsWindows()) { dotCharOk = ConsoleUtil.CheckIfCharInFont(dotChar, new Font(currentFont, 10)); } var brailleCharOk = false; if (OperatingSystem.IsWindows()) { brailleCharOk = ConsoleUtil.CheckIfCharInFont(brailleChar, new Font(currentFont, 10)); } // Console.WriteLine($"Dot: {dotCharOk}, Braille: {brailleCharOk}"); Console.Write($"Console Detection: "); if (conEmuDetected) { Console.WriteLine("ConEmu", colorScheme.DarkDefault); config.DisplayConfiguration.IsConEmuDetected = true; config.DisplayConfiguration.SupportsExtendedUnicode = true; } else if (powershellDetected) { Console.WriteLine("Powershell", colorScheme.DarkDefault); config.DisplayConfiguration.IsPowershellDetected = true; } else { Console.WriteLine("Command Prompt", colorScheme.DarkDefault); config.DisplayConfiguration.IsCommandPromptDetected = true; } } Console.Write($"Test runner arguments: "); Console.WriteLine(options.TestRunnerArguments.MaxLength(360), colorScheme.DarkDefault); Console.WriteLine($"Initializing performance counters...", colorScheme.Default); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { #pragma warning disable CA1416 // Validate platform compatibility runContext.PerformanceCounters.CpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); runContext.PerformanceCounters.DiskCounter = new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total"); #pragma warning restore CA1416 // Validate platform compatibility } } catch (Exception ex) { Console.WriteLine($"Error initializing performance counters... {ex.Message}", colorScheme.Error); // unable to use performance counters. // possibly need to run C:\Windows\SysWOW64> lodctr /r } }