如何检测Console.In(stdin)是否已被重定向?

时间:2010-08-10 20:38:48

标签: c# console redirect stdin

我想编写一个具有不同行为的控制台应用程序,具体取决于输入是来自键盘还是来自文件。

有可能吗?在C#中最优雅的方法是什么?

4 个答案:

答案 0 :(得分:49)

您可以通过p /调用Windows FileType()API函数找到答案。这是一个助手类:

using System;
using System.Runtime.InteropServices;

public static class ConsoleEx {
    public static bool IsOutputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
    }
    public static bool IsInputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
    }
    public static bool IsErrorRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
    }

    // P/Invoke:
    private enum FileType { Unknown, Disk, Char, Pipe };
    private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
    [DllImport("kernel32.dll")]
    private static extern FileType GetFileType(IntPtr hdl);
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetStdHandle(StdHandle std);
}

用法:

bool inputRedirected = ConsoleEx.IsInputRedirected;

更新:这些方法已添加到.NET 4.5中的Console类中。如果没有归属,我可能会添加:(只需使用相应的方法而不是此辅助类。

https://msdn.microsoft.com/en-us/library/system.console.isoutputredirected.aspx https://msdn.microsoft.com/en-us/library/system.console.isinputredirected.aspx https://msdn.microsoft.com/en-us/library/system.console.iserrorredirected.aspx

答案 1 :(得分:5)

有趣的是,当管道打开时,System.Console.WindowHeightSystem.Console.WindowWidth参数,我发现这是由于代码中有多个ArgumentOutOfRangeException不关心控制台大小为零的路径。

跨平台:Linux和Windows上的 MS dotNET Mono 下的行为相同(我没有在Mac上试过它)。

当管道传输STDIN或STDOUT时,控制台大小设置为0.因此,根据Hans的实现,我的代码如下:

using System;


 public static class ConsoleEx {
        public static bool IsConsoleSizeZero {
            get {
                try {
                    return (0 == (Console.WindowHeight + Console.WindowWidth));
                }
                catch (Exception exc){
                    return true;
                }
            }
        }
        public static bool IsOutputRedirected {
            get { return IsConsoleSizeZero && !Console.KeyAvailable; }
        }
        public static bool IsInputRedirected {
            get { return IsConsoleSizeZero && Console.KeyAvailable; }
        }
}

2016年更新 : 添加了对IsConsoleSizeZero代码的异常处理,以提高代码在更广泛的上下文中的可用性。

代码似乎仍然运作良好,至少从使用MonoDevelop / Xamarin Studio时的经验来讲。

相关

答案 2 :(得分:1)

由于框架4.5存在属性Console.IsInputRedirected。 8 - )

请参阅MSDN

https://msdn.microsoft.com/de-de/library/system.console.isinputredirected(v=vs.110).aspx

答案 3 :(得分:1)

洛伦兹的回答是一个良好的开端,但不幸的是只能用一个灵感。运行控制台应用程序有更多模式。

  1. 标准运行(在控制台中,没有任何重定向)

    在控制台中,一切都按预期工作。

  2. 使用标准输入和/或标准输出重定向从控制台重定向执行

    e.g。

    type input_file.txt | application.exe (在 Windows 中),或application.exe <input_file.txt用于输入重定向

    (将type替换为 Linux 中的cat

    输出重定向

    application.exe | grep patternapplication.exe >output_file.txt

    type input_file.txt | application.exe | grep patternapplication.exe <input_file.txt >output_file.txt用于输入和输出重定向

  3. 使用标准输出错误输出重定向从控制台重定向执行

    e.g。 application.exe >output_file.txt 2>error_file.txt

  4. 使用隐藏控制台执行并重定向输入/输出/错误

    e.g。来自GUI应用程序(控制台根本不可见)

  5. 使用隐藏控制台执行不使用重定向输入/输出/错误

  6. 这些模式中的每一种都具有自己的功能&#39;。 Console.WindowHeightConsole.WindowWidth以标准方式在第一和第二模式的 Windows 中工作。在 Linux 中,第二和第三模式的返回值为。因此,在Linux中,您无法检测仅重定向的输入。

    因此,Lorenz答案的代码不能用于检测所有情况下的重定向。只有在无输出来控制(例如第3种模式)时才会引发IOExceptionConsole.WindowHeight时的Console.WindowWidth对于 Windows

    要检测 输入 重定向(仅限 Windows ,请使用此功能:

    private static bool IsInputRedirected()
    {
      try
      {
        if (Console.KeyAvailable)
        {
          return (false);
        }
      }
      catch (InvalidOperationException)
      {
        return (true);
      }
      return (false);
    }
    

    对于所有其他重定向和操作系统...尝试尝试如何检测它们。不同的控制台属性和功能&#39;工作&#39;不同模式的(抛出异常或零返回值)

    Windows 7 .NET Framework 4 Client ProfileMono JIT compiler version 4.2.1 (Debian 4.2.1.102+dfsg2-7ubuntu4)上进行了测试。

      

    重要:

         

    不要将此功能用于Linux 中的输入重定向(检测正在运行的操作系统/平台,例如Mono for Windows),因为当您错误地期望重定向并且重定向不活动时会导致更多麻烦