Skip to content

Instantly share code, notes, and snippets.

@drehren
Created September 10, 2017 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drehren/377fc0abe6029f174bbf0193c984cbe3 to your computer and use it in GitHub Desktop.
Save drehren/377fc0abe6029f174bbf0193c984cbe3 to your computer and use it in GitHub Desktop.
Reset Console Redirection for VS2017-hosted Windows Application
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace Utilities
{
static class ResetConsoleRedirection
{
/// <summary>
/// This method will check if the Console Window is opened and redirected.
/// You need to call this method BEFORE ANY call to System.Console to avoid setting stuff there.
/// </summary>
public static void CheckAndReset()
{
// If the console has already been allocated, it means that this is a console application and
// it doesn't need to be further messed with.
if (ConsoleStarted())
{
return;
}
// Check for ouput redirection
if (IsStdHandleRedirected(NativeMethods.StdHandle.Output))
{
Reset(NativeMethods.StdHandle.Output);
}
// Check for input redirection; normally it isn't
if (IsStdHandleRedirected(NativeMethods.StdHandle.Input))
{
Reset(NativeMethods.StdHandle.Input);
}
}
private static void Reset(NativeMethods.StdHandle stdHandle)
{
string name = stdHandle == NativeMethods.StdHandle.Input ? "CONIN$" : "CONOUT$";
SafeFileHandle std = NativeMethods.CreateFile(name,
NativeMethods.DesiredAccess.GENERIC_READ
| NativeMethods.DesiredAccess.GENERIC_WRITE,
NativeMethods.ShareMode.FILE_SHARE_READ
| NativeMethods.ShareMode.FILE_SHARE_WRITE,
IntPtr.Zero,
NativeMethods.CreationDisposition.OPEN_EXISTING,
0,
IntPtr.Zero);
NativeMethods.SetStdHandle(stdHandle, std);
}
/// <summary>
/// See https://referencesource.microsoft.com/#mscorlib/system/console.cs,f108bd7fd3c5ebdc
/// </summary>
/// <param name="stdHandle"> The standard handle to check. </param>
/// <returns> True if the handle was redirected, false otherwise. </returns>
private static bool IsStdHandleRedirected(NativeMethods.StdHandle stdHandle)
{
SafeFileHandle safeIOHandle = NativeMethods.GetStdHandle(stdHandle);
NativeMethods.FileType fileType = NativeMethods.GetFileType(safeIOHandle);
if ((fileType & NativeMethods.FileType.Char) != NativeMethods.FileType.Char)
return true;
uint mode;
bool success = NativeMethods.GetConsoleMode(safeIOHandle, out mode);
return !success;
}
private static bool ConsoleStarted()
{
return !NativeMethods.AllocConsole();
}
static class NativeMethods
{
[Flags]
internal enum DesiredAccess : uint
{
NONE = 0x0,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
}
[Flags]
internal enum ShareMode : uint
{
NONE = 0x0,
FILE_SHARE_READ = 0x00000001,
FILE_SHARE_WRITE = 0x00000002,
}
internal enum CreationDisposition : uint
{
OPEN_EXISTING = 3,
}
internal enum StdHandle
{
Input = -10,
Output = -11,
}
[Flags]
internal enum FileType : uint
{
Char = 0x0002,
Disk = 0x0001,
Pipe = 0x0003,
Remote = 0x8000,
Unknown = 0x0000,
}
[DllImport("kernel32.dll")]
internal static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeFileHandle CreateFile(string lpFileName,
DesiredAccess dwDesiredAccess,
ShareMode dwShareMode,
IntPtr lpSecurityAttributes,
CreationDisposition dwCreationDisposition,
UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern SafeFileHandle GetStdHandle(StdHandle nStdHandle);
[DllImport("kernel32.dll")]
internal static extern FileType GetFileType(SafeHandle hFile);
[DllImport("kernel32.dll")]
internal static extern bool GetConsoleMode(SafeHandle hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
internal static extern bool SetStdHandle(StdHandle nStdHandle, SafeHandle hHandle);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment