一尘不染

使用AllocConsole和目标体系结构x86时没有控制台输出

c#

我有一个WinForms项目,如果用户想要一个调试控制台,我可以分配一个控制台AllocConsole()

所有控制台输出都可以在目标体系结构设置为“任何CPU”的情况下正常工作,但是当我将其更改为“
x86”时,它不会输出任何内容(Console.Read()仍然可以正常工作)。如果我直接打开EXE,则输出有效。看起来Visual
Studio将其重定向到它自己的“输出”窗口中。

我也尝试了这个答案,但是没有用,我也尝试了Console.SetOut(GetStdHandle(-11)),也没有用。

将目标体系结构设置为“任何CPU”对我来说是没有选择的。

所以这是我的两个问题:

  • 为什么只有在目标体系结构设置为x86时才如此?
  • 在Visual Studio内部运行时,如何输出到控制台?

阅读 741

收藏
2020-05-19

共1个答案

一尘不染

启用“启用本机代码调试”后,从中选择的控制台输出AllocConsole将重定向到调试输出窗口。

仅在x86而不是AnyCPU中发生这种情况的原因是,您只能在x86应用程序中调试本机代码。

请注意,仅当使用创建的控制台出现此行为AllocConsole。控制台应用程序的输出未重定向。

编辑:控制台不输出文本的另一个原因是,您在调用之前已写入控制台AllocConsole

无论出于何种原因,此代码都会在重定向后恢复输出,并在无效时重新打开控制台。它使用 魔幻数字7stdout通常等于它的句柄。

using System;
using System.IO;
using System.Runtime.InteropServices;

public static class ConsoleHelper
{
    public static void CreateConsole()
    {
        AllocConsole();

        // stdout's handle seems to always be equal to 7
        IntPtr defaultStdout = new IntPtr(7);
        IntPtr currentStdout = GetStdHandle(StdOutputHandle);

        if (currentStdout != defaultStdout)
            // reset stdout
            SetStdHandle(StdOutputHandle, defaultStdout);

        // reopen stdout
        TextWriter writer = new StreamWriter(Console.OpenStandardOutput()) 
        { AutoFlush = true };
        Console.SetOut(writer);
    }

    // P/Invoke required:
    private const UInt32 StdOutputHandle = 0xFFFFFFF5;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetStdHandle(UInt32 nStdHandle);
    [DllImport("kernel32.dll")]
    private static extern void SetStdHandle(UInt32 nStdHandle, IntPtr handle);
    [DllImport("kernel32")]
    static extern bool AllocConsole();
}

请参阅如何检测Console.In(stdin)是否已重定向?另一种检测控制台句柄是否已重定向的方法。

2020-05-19