【问题标题】:How can I determine whether Console.Out has been redirected to a file?如何确定 Console.Out 是否已重定向到文件?
【发布时间】:2010-10-19 03:17:01
【问题描述】:

如果我的程序正在打印到控制台,我会根据 Console.WindowWidth 通过插入换行符以某种方式执行自动换行 - 这非常有效。

但是,如果程序的输出被重定向到一个文件或另一个程序,我希望它跳过自动换行。我怎样才能检测到这种情况?

Console.WindowWidth 在两种情况下都返回相同的数字。

如果解决方案能够区分重定向的 Console.Out 和重定向的 Console.Error,

奖励分。

【问题讨论】:

标签: c# .net console


【解决方案1】:

.NET 4.5 添加了Console.IsOutputRedirectedConsole.IsErrorRedirected

【讨论】:

    【解决方案2】:

    p/invoke GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)),或调用类似GetConsoleScreenBufferInfo 的无害控制台函数来检查无效句柄错误。如果您想了解标准错误,请使用STD_ERROR_HANDLE。我相信您甚至可以比较 GetStdHandle(STD_OUTPUT_HANDLE)GetStdHandle(STD_ERROR_HANDLE) 返回的句柄来检测像 2>&1 这样的东西。

    【讨论】:

    • 是的,与基于反射的东西相比,它工作得非常完美,而且更具前瞻性。谢谢!
    【解决方案3】:

    虽然这有点阴暗,并且可能无法保证有效,但您可以试试这个:

    bool isRedirected;
    
    try
    {
        isRedirected = Console.CursorVisible && false;
    }
    catch
    {
        isRedirected = true;
    }
    

    在控制台重定向时调用 CursorVisible 会引发异常。

    【讨论】:

    • 似乎适用于标准输出。不区分仅重定向 stderr、仅 stdout 或两者都重定向的情况。不过对于某些用例来说仍然可以。
    • 当 stdout 被重定向时它总是对我有用,我想这真的是唯一重要的,对吧?
    【解决方案4】:

    您需要使用反射 - 有点脏,但以下方法会起作用:

    static bool IsConsoleRedirected()
    {
        var writer = Console.Out;
        if (writer == null || writer.GetType ().FullName != "System.IO.TextWriter+SyncTextWriter") return true;
        var fld = writer.GetType ().GetField ("_out", BindingFlags.Instance | BindingFlags.NonPublic);
        if (fld == null) return true;
        var streamWriter = fld.GetValue (writer) as StreamWriter;
        if (streamWriter == null) return true;
        return streamWriter.BaseStream.GetType ().FullName != "System.IO.__ConsoleStream";
    }
    

    【讨论】:

    • 您如何确保它也能在 .NET 的下一个版本中工作? :)
    • 这就是为什么它有点脏。但这是唯一的选择。
    • 虽然它会做一些令人讨厌的事情,比如检查私有字段的类型的名称......它仍然是迄今为止最好的解决方案,而且其他的也没有那么讨厌。
    • 我认为这是一种不错的技术。你肯定希望它被单元测试覆盖,以确保它在框架版本更改中工作。
    【解决方案5】:

    为什么输出会包含在重定向文件中?控制台所做的换行不是通过换行符进行的。换句话说这个字符串:

    你好,我叫安德鲁·黑尔

    会像这样包裹在一个瘦小的控制台中:

    你好我的名字
    e 是安德鲁
    野兔

    但如果你要将输出重定向到一个文件,它会这样写:

    你好,我叫安德鲁·黑尔

    因为输出中没有真正的换行符。

    【讨论】:

    • 完全正确 - 在一个瘦小的控制台中,它会以一种蹩脚的方式包装。这就是为什么我们在输出到控制台之前对自己进行包装(通过插入换行符和适当的缩进)。显然,这种方法还包装了重定向的输出,这是我们试图避免的。
    【解决方案6】:

    不要那样做!只需传递一个额外的命令行参数,该参数指定您要应用的格式。无论是使用您的应用程序的人还是使用您的代码的人,它都更简单、更简洁、更容易理解。

    【讨论】:

    • 我不同意。程序应该尽可能地自己解决问题,而不是每次都询问用户。
    • 也不同意。看看 git 的行为。像git diff 这样的命令通过less 管道和某种着色器,除非它们被管道或重定向到文件。
    猜你喜欢
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 2014-04-07
    • 1970-01-01
    • 2016-12-19
    • 2010-09-24
    相关资源
    最近更新 更多