2

我有一个 GUI C# 应用程序,它使用使用AllocConsole. 它在正常情况下工作,但是当应用程序在 Visual Studio 下以调试模式启动时,所有输出都会在 Visual Studio 输出窗口中结束。我该如何阻止它?

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

4

2 回答 2

6

我的解决方案是自己将标准流重置为新创建的控制台。这是代码:

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);
}
于 2012-12-31T10:40:29.107 回答
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

于 2012-10-24T14:09:18.507 回答