Console.Out initialized lazily. The first time it is accessed, the run time calls GetStdHandle(STD_OUTPUT_HANDLE) to get the standard output descriptor. If this call occurs before the AttachConsole called, you get a file descriptor for redirection. If this call comes up after that, you get a console output descriptor.
The following class corrects standard output and error descriptors. If you run the application from the console, you will notice that after the next request any output will appear. You can avoid this with start /wait .
using System; using System.Runtime.InteropServices; namespace SomeProject { class GuiRedirect { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(StandardHandle nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle); [DllImport("kernel32.dll", SetLastError = true)] private static extern FileType GetFileType(IntPtr handle); private enum StandardHandle : uint { Input = unchecked((uint)-10), Output = unchecked((uint)-11), Error = unchecked((uint)-12) } private enum FileType : uint { Unknown = 0x0000, Disk = 0x0001, Char = 0x0002, Pipe = 0x0003 } private static bool IsRedirected(IntPtr handle) { FileType fileType = GetFileType(handle); return (fileType == FileType.Disk) || (fileType == FileType.Pipe); } public static void Redirect() { if (IsRedirected(GetStdHandle(StandardHandle.Output))) { var initialiseOut = Console.Out; } bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error)); if (errorRedirected) { var initialiseError = Console.Error; } AttachConsole(-1); if (!errorRedirected) SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output)); } } }
source share