【问题标题】:Check if output is redirected检查输出是否被重定向
【发布时间】:2010-11-13 06:22:02
【问题描述】:

我有一个用 C# 编写的控制台应用程序,它处理一些数据然后打印结果。在结果可用之前,会有一点动画( / - \ | )和不断更新的进度百分比( xx% )。

显然,如果用户重定向我的应用程序的输出,这将被打印到输出重定向到的文本文件中。如果可能的话,我想避免这种情况。

那么有没有办法检测我的应用程序的输出是否被重定向? 我正在考虑仅在使用指定参数运行时显示进度指示器,但我希望有人能给我一个好的答案。

【问题讨论】:

标签: c# .net redirect console


【解决方案1】:

你不能。重定向的输出完全超出了执行程序的范围。但是,您可以添加一个命令行选项来禁用漂亮的输出,以便它也可以被重定向使用。

编辑:您可以(现在)... 使用 .NET 4.5 及更高版本(请参阅 Matt Brooks' answer)。

【讨论】:

  • 和我想的一样 >.
  • 如果我想根据输入是否来自控制台来猜测一些默认设置怎么办?例如,在 SQL 解析器中,最好在接受来自键盘的命令时打印结果记录集,但在解析文件时保持沉默。或者如果我想在写入文件时输出 Unicode BOM 怎么办?在这些情况下应该使用哪些模式?
  • @himself:如果您想处理诸如编写 BOM 之类的事情,请询问输出参数。根据操作系统,您可以检测您是否在控制台上运行,但至少可以说是令人费解的,而且我认为它不适用于 Windows/C#。您最简单的选择是接受-q(安静)或类似选项,或者如果您已启用所述选项以写入文件,则可能假设您正在获得编程输入。
【解决方案2】:

我不会尝试确定内容是否被重定向,而是使用 Console.WriteLine(或 Console.Out.WriteLine)来打印您的结果并使用 Console.Error.Write 来更新您的状态。屏幕输出将正确显示,但不会反映在文本文件中。

【讨论】:

  • 好主意,但是将非错误数据写入标准错误相当误导。
  • 具有误导性,是的,但仍然是一种常见的做法。
【解决方案3】:

您可以使用本机方法GetConsoleMode 来查看stdout 是否进入控制台。

WriteConsole的文档中的备注建议了此方法:

...判断输出句柄是否为控制台句柄(一种方法是调用GetConsoleMode函数,检查是否成功)...

【讨论】:

  • 当然,这意味着使用不安全的本机方法……但这是可能的。
  • 某些属性调用GetConsoleMode 并抛出失败,例如Console.CursorVisible。这将允许在不使用 P/Invoke 的情况下检查控制台输出。
【解决方案4】:

事实证明,它很快就会以优雅和跨平台的方式提供: link.

【讨论】:

    【解决方案5】:

    或许,你可以试试这个:

    public enum FileType : uint
    {
        FILE_TYPE_UNKNOWN = 0x0000,
        FILE_TYPE_DISK = 0x0001,
        FILE_TYPE_CHAR = 0x0002,
        FILE_TYPE_PIPE = 0x0003,
        FILE_TYPE_REMOTE = 0x8000,
    }
    
    public enum STDHandle : uint
    {
        STD_INPUT_HANDLE = unchecked((uint)-10),
        STD_OUTPUT_HANDLE = unchecked((uint)-11),
        STD_ERROR_HANDLE = unchecked((uint)-12),
    }
    
    [DllImport("Kernel32.dll")]
    static public extern UIntPtr GetStdHandle(STDHandle stdHandle);
    [DllImport("Kernel32.dll")]
    static public extern FileType GetFileType(UIntPtr hFile);
    
    static public bool IsOutputRedirected()
    {
        UIntPtr hOutput = GetStdHandle(STDHandle.STD_OUTPUT_HANDLE);
        FileType fileType = (FileType)GetFileType(hOutput);
        if (fileType == FileType.FILE_TYPE_CHAR)
            return false;
        return true;
    }
    

    如果标准输出没有被重定向,GetFileType() 的输出应该是 0x0002。 这对我有用。 :)

    【讨论】:

      【解决方案6】:

      Console.Write("whatever")(和WriteLine)实际上将数据写入Console.Out后面的流中。 要始终在控制台上显示进度条而不将其写入文件,无论输出是否重定向到文件,请改用错误流:

      Console.Error.Write("<your progress bar>");

      当应用程序使用 > 运算符 (DIR C:\*.*>MORE) 重定向输出时,仅重定向 Console.Out 而不会重定向 Console.Error

      【讨论】:

        【解决方案7】:

        从 .NET Framework 4.5 开始,您可以使用 Console.IsOutputRedirected property 来检测这一点。

        还有Console.IsErrorRedirected

        【讨论】:

          猜你喜欢
          • 2012-06-16
          • 2012-02-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-02
          • 2011-01-06
          相关资源
          最近更新 更多