如何检测是否Console.In(标准输入)已经重定向?如何检测是否Console.In(标准输入)

2019-05-11 05:55发布

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

可能吗? 什么是最优雅的方式做它在C#中?

Answer 1:

您可以通过P /找出调用Windows的文件类型()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这些方法。 没有归属我要补充:(只需用相应的方法,而不是这个辅助类。

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



Answer 2:

有趣的是,当管道打开, System.Console.WindowHeightSystem.Console.WindowWidth参数都是 ,这是我发现,由于多种ArgumentOutOfRangeException未理控制台的大小为零的代码路径。

跨平台 :该行为是在MS DOTNETMono在Linux和Windows相同的(我还没有尝试过在Mac上)。

当任STDIN或STDOUT的管道,控制台的大小设置为0的汉斯的实施从而建立,我的代码如下:

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的经验之谈。

相关阅读

  • MSDN: KeyAvailable

  • 设置System.Console.WindowHeight抛出单下System.NotSupportedException 。



Answer 3:

因为框架4.5该属性存在Console.IsInputRedirected。 8-)

参见MSDN

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



Answer 4:

洛伦茨答案是一个良好的开端,但遗憾的是只能使用一个灵感。 有用于运行一个控制台应用程序更多的模式。

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

    一切都按预期的控制台。

  2. 具有重定向执行来自标准输入和/或标准输出重定向控制台

    例如

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

    (替代typecatLinux中)

    要么

    application.exe | grep pattern application.exe | grep patternapplication.exe >output_file.txt输出重定向

    要么

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

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

    例如application.exe >output_file.txt 2>error_file.txt

  4. 具有隐藏控制台和重定向输入/输出/执行错误

    例如,来自应用程序的GUI(控制台是不可见的话)

  5. 隐藏控制台执行没有输入/输出/错误的重定向

每个模式都有它自己的“特色”。 该Console.WindowHeightConsole.WindowWidthWindows工作的标准方式第一和第二模式。 在Linux中在第二和第三模式的返回值是 。 因此在Linux中无法检测输入仅重定向。

因此,从洛伦茨答案的代码不能用于在所有情况下检测重定向。 该IOException阅读时Console.WindowHeightConsole.WindowWidth被抛出时,才会有没有输出到控制台(如第3模式),仅适用于Windows。

(仅在Windows)来检测输入重定向使用此功能:

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

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

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

重要:

不要使用此功能,输入在Linux中重定向(检测运行OS /平台,如单适用于Windows),因为它可能导致更多的麻烦,当你错误地希望重定向和重定向不活跃。



文章来源: How to detect if Console.In (stdin) has been redirected?