如何停止VC#将控制台输出重定向到输出窗口?

3

我有一个使用AllocConsole创建的控制台的GUI C#应用程序。在正常情况下它可以工作,但是当在Visual Studio的调试模式下运行时,所有的输出都会出现在Visual Studio的输出窗口中。我该如何停止这种情况发生?

我正在使用C# 3.5和Visual Studio Pro 2010。进程托管选项已关闭。


不,如果C#代码实际上使用Console.Write/Line(),那么它应该可以正常工作。如果它使用Debug.Print或跟踪之类的东西,那么输出将由OutputDebugString()编写,并最终出现在调试器窗口中。输出窗口。考虑使用SysInternals的DebugView实用程序。 - Hans Passant
我使用Console.WriteLine,结果它出现在Visual Studio输出窗口中,而不是我的控制台中。 - Don Reba
很难解释。尝试关闭托管进程选项。 - Hans Passant
谢谢您的尝试。进程托管选项已经关闭。 - Don Reba
2个回答

7
我的解决方案是自己将标准流重置到新创建的控制台上。以下是代码:
public static class ConsoleHelper
{
    /// <summary>
    /// Allocates a console and resets the standard stream handles.
    /// </summary>
    public static void Alloc()
    {
        if (!AllocConsole())
            throw new Win32Exception();
        SetStdHandle(StdHandle.Output, GetConsoleStandardOutput());
        SetStdHandle(StdHandle.Input,  GetConsoleStandardInput());
    }

    private static IntPtr GetConsoleStandardInput()
    {
        var handle = CreateFile
            ( "CONIN$"
            , DesiredAccess.GenericRead | DesiredAccess.GenericWrite
            , FileShare.ReadWrite
            , IntPtr.Zero
            , FileMode.Open
            , FileAttributes.Normal
            , IntPtr.Zero
            );
        if (handle == InvalidHandleValue)
            throw new Win32Exception();
        return handle;
    }

    private static IntPtr GetConsoleStandardOutput()
    {
        var handle = CreateFile
            ( "CONOUT$"
            , DesiredAccess.GenericWrite | DesiredAccess.GenericWrite
            , FileShare.ReadWrite
            , IntPtr.Zero
            , FileMode.Open
            , FileAttributes.Normal
            , IntPtr.Zero
            );
        if (handle == InvalidHandleValue)
            throw new Win32Exception();
        return handle;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    private static extern bool SetStdHandle(StdHandle nStdHandle, IntPtr hHandle);

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateFile
        (                               string         lpFileName
        , [MarshalAs(UnmanagedType.U4)] DesiredAccess  dwDesiredAccess
        , [MarshalAs(UnmanagedType.U4)] FileShare      dwShareMode
        ,                               IntPtr         lpSecurityAttributes
        , [MarshalAs(UnmanagedType.U4)] FileMode       dwCreationDisposition
        , [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes
        ,                               IntPtr         hTemplateFile
        );

    [Flags]
    enum DesiredAccess : uint
    {
        GenericRead    = 0x80000000,
        GenericWrite   = 0x40000000,
        GenericExecute = 0x20000000,
        GenericAll     = 0x10000000
    }

    private enum StdHandle : int
    {
        Input  = -10,
        Output = -11,
        Error  = -12
    }

    private static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
}

DesiredAccess 属于哪个命名空间? - CAD bloke
啊,看起来它是从http://www.pinvoke.net/default.aspx/kernel32.createfile派生的。 - CAD bloke

0

您可以通过不同的应用程序启动方式来重定向输出,例如:

(参考文献1)
//
// Setup the process with the ProcessStartInfo class.
//
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = @"C:\MyExe.exe"; // Specify exe name.
start.UseShellExecute = false;
start.RedirectStandardOutput = true;

如果需要,您也可以通过以下方式消耗输出(参考文献1)

//
// Start the process.
//
using (Process process = Process.Start(start))
{
    //
    // Read in all the text from the process with the StreamReader.
    //
    using (StreamReader reader = process.StandardOutput)
    {
    string result = reader.ReadToEnd();
    Console.Write(result);
    }
}

参考资料: (1) http://www.dotnetperls.com/redirectstandardoutput


我没有重定向另一个可执行文件的流。 - Don Reba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接