/// <summary> /// Function to open the data store for writing. /// </summary> /// <param name="initialMessage">[Optional] The initial message to write.</param> public void Open(string initialMessage = null) { if (Interlocked.Exchange(ref _hasConsole, 1) == 1) { return; } // Check for an existing console first. using (Stream stdIn = Console.OpenStandardInput()) { // If it does not exist, then create one. if (stdIn == Stream.Null) { if (!KernelApi.AllocConsole()) { return; } _ownsConsole = true; } } // If we have Enable Native Debugging turned on, all output is redirected to the debug window. // This will reset that back to our logging window. if (Console.IsOutputRedirected) { const uint genericRead = 0x80000000; const uint genericWrite = 0x40000000; IntPtr filePtr = KernelApi.CreateFileW("CONOUT$", (genericRead | genericWrite), (uint)FileShare.ReadWrite, IntPtr.Zero, (uint)FileMode.Open, 0, IntPtr.Zero); var handle = new SafeFileHandle(filePtr, true); if (handle.IsInvalid) { handle.Dispose(); return; } KernelApi.SetStdHandle(KernelApi.StdOutputHandle, filePtr); var stream = new FileStream(handle, FileAccess.Write); var writer = new StreamWriter(stream, Encoding.Default) { AutoFlush = true }; Console.SetOut(writer); if (KernelApi.GetConsoleMode(filePtr, out uint consoleMode)) { KernelApi.SetConsoleMode(filePtr, consoleMode | 0x200); } } if (string.IsNullOrWhiteSpace(initialMessage)) { return; } Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(initialMessage); Console.ResetColor(); }