2

I want to create a console window and print some info on it when debugging my program. VS 2010 does not give me the option of setting different Output types for my program depending on whether its in debug or release mode, so I resorted to creating a Console window manually like so:

[DllImport("kernel32.dll")]
public static extern Int32 AllocConsole();

static void Main()
{
#if DEBUG
    AllocConsole();
#endif
....

That pops open a console window, but nothing gets written to it. I tried a bunch of other pinvoke (AttachConsole etc...) that did nothing. Then I finally tried running the application outside of Visual Studio, and the Console Window worked. Apparently Visual Studio is eating up all my Console.WriteLines!

How can I fix this?

Bob Coder
  • 391
  • 3
  • 13
  • 1
    That should work just fine. Look in the VS Output window. And in general favor Debug.Print() to display debugging output there. – Hans Passant Mar 22 '13 at 20:11
  • Or `Trace.Write`...or wait, now I gotta think: does VS wire up `TraceListeners` automatically? Hmm...*clattety-clack-clack* - yes, it does. – JerKimball Mar 22 '13 at 20:17
  • Well, I still would prefer for it to be displayed on the console window, not in VS' output window. – Bob Coder Mar 22 '13 at 20:24

3 Answers3

11

Having encountered the same issue, here is some code that appears to restore console output for me after the call to AllocConsole:

    private static void OverrideRedirection()
    {
        var hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        var hRealOut = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, FileShare.Write, IntPtr.Zero, FileMode.OpenOrCreate, 0, IntPtr.Zero);
        if (hRealOut != hOut)
        {
            SetStdHandle(STD_OUTPUT_HANDLE, hRealOut);
            Console.SetOut(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true });
        }
    }

P/Invokes as follows:

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);

    public const int STD_OUTPUT_HANDLE = -11;
    public const int STD_INPUT_HANDLE  = -10;
    public const int STD_ERROR_HANDLE  = -12;

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPTStr)] string         filename,
                                           [MarshalAs(UnmanagedType.U4)]     uint           access,
                                           [MarshalAs(UnmanagedType.U4)]     FileShare      share,
                                                                             IntPtr         securityAttributes,
                                           [MarshalAs(UnmanagedType.U4)]     FileMode       creationDisposition,
                                           [MarshalAs(UnmanagedType.U4)]     FileAttributes flagsAndAttributes,
                                                                             IntPtr         templateFile);

    public const uint GENERIC_WRITE = 0x40000000;
    public const uint GENERIC_READ  = 0x80000000;
Dave Cluderay
  • 7,268
  • 1
  • 29
  • 28
  • 3
    I cannot upvote this reply enough; the magical `CONOUT$` and `CONIN$` files are among the most poorly-documented parts of Windows, and really should get more attention. What little MSDN documentation on them that exists can be found at this link: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682075(v=vs.85).aspx – Sean Werkema Oct 26 '16 at 20:18
  • You don't need `if (hRealOut != hOut)`... `CreateFile` will always return a unique handle which will be inequal to the return value of `GetStdHandle()` even if both do refer to the same object. – Ben Voigt Nov 29 '16 at 16:42
3

I got the same issue. Turns out writing to the console works in visual studio only when debugging in hosted process. Go to Project Properties -> Debug -> Enable Debuggers and make sure 'Enable Visual Studio hosting process' is checked.

ghord
  • 13,260
  • 6
  • 44
  • 69
  • I also found in VS2013 that enabling "Sql Server Debugging" prevents the console from working, probably due to the reason ghord mentioned. – GadgetNC Feb 21 '14 at 20:49
0

As I have already said here, you can try to run the VS as administrator. That worked for me.

Community
  • 1
  • 1
Andrey Bobrov
  • 201
  • 1
  • 13