static void DisplayLogo(ColorScheme colorScheme) { // display logo if (!Console.IsOutputRedirected) { Console.Clear(); var fontBytes = ResourceLoader.Load("big.flf"); var font = Colorful.FigletFont.Load(fontBytes); ColorfulConsole.WriteAscii(Constants.ApplicationName, font, colorScheme.Highlight); ColorfulConsole.WriteLine($"Version {Assembly.GetExecutingAssembly().GetName().Version}", colorScheme.DarkHighlight); ColorfulConsole.WriteLine(new string(UTF8Constants.BoxHorizontal, Console.WindowWidth - 5), colorScheme.DarkHighlight); } }
/// <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 } }
private static bool Start(Options options, ApplicationConfiguration config) { var isTestPass = false; var hasAnotherRunner = true; UpdateConfigOverrides(options, config); var colorScheme = new ColorScheme(config.ColorScheme); Console.SetColorScheme(colorScheme); var runNumber = 0; var runContext = new RunContext { TestHistoryDatabaseProvider = new TestHistoryDatabaseProvider(config) }; HandleCustomOperations(options, colorScheme, runContext); DisplayLogo(colorScheme); AutoUpdate(options, colorScheme); DisplayInitializationScreen(options, config, colorScheme, runContext); while (!_applicationQuitRequested && runNumber < options.Repeat) { runNumber++; if (options.TestRunner.HasValue) { _launcher = new TestRunnerLauncher(options); _launcher.OnScanStarted = () => { Console.WriteLine($"Scanning test assemblies...", colorScheme.Default); }; _launcher.OnScanCompleted = () => { Console.WriteLine($"Done scanning test assemblies!", colorScheme.Default); }; _launcher.OnTestRunnerExit += Launcher_OnTestRunnerExit; // launch test runner in another process if asked System.Diagnostics.Debug.WriteLine($"[{DateTime.Now.TimeOfDay}] Test Runner started!"); var canLaunch = _launcher.QueueTestRunners(); if (!canLaunch) { Console.WriteLine($"Error launching the test runner!", colorScheme.Default); } } var runnerTask = () => { // start the process immediately return(_launcher?.NextProcess() ?? false); }; while (!_applicationQuitRequested && hasAnotherRunner) /*(_launcher?.NextProcess() ?? false)*/ { System.Diagnostics.Debug.WriteLine($"[{DateTime.Now.TimeOfDay}] Commander Launching {config.DisplayMode}"); // blocking switch (config.DisplayMode) { case DisplayMode.LogFriendly: (isTestPass, hasAnotherRunner) = RunLogFriendly(options, config, colorScheme, runNumber, runContext, runnerTask); break; case DisplayMode.FullScreen: (isTestPass, hasAnotherRunner) = RunFullScreen(options, config, colorScheme, runNumber, runContext, runnerTask); break; default: Console.WriteLine($"Unknown DisplayMode '{config.DisplayMode}'"); break; } } if (_launcher != null) { // kill the test runner if it's still running at this point _launcher.Kill(); //Console.Error.WriteLine($"Exit code: {launcher.ExitCode}"); //Console.Error.WriteLine($"OUTPUT: {launcher.ConsoleOutput}"); //Console.Error.WriteLine($"ERRORS: {launcher.ConsoleError}"); ParseConsoleRunnerOutput(isTestPass, options, config, colorScheme); _launcher.Dispose(); runContext?.PerformanceCounters?.CpuCounter?.Dispose(); runContext?.PerformanceCounters?.DiskCounter?.Dispose(); } } ResetColor(); return(isTestPass);