代码之家  ›  专栏  ›  技术社区  ›  jpbochi

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

  •  25
  • jpbochi  · 技术社区  · 16 年前

    我想编写一个控制台应用程序,根据输入是来自键盘还是来自文件,比如说,有不同的行为。

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

    4 回复  |  直到 16 年前
        1
  •  55
  •   Hans Passant    9 年前

    您可以通过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;
    

    更新:这些方法被添加到.NET4.5中的控制台类中。如果没有属性,我可以添加:(简单地使用相应的方法,而不是这个helper类。

    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

        2
  •  6
  •   Community Mohan Dere    9 年前

    有趣的是,当管道打开时 System.Console.WindowHeight System.Console.WindowWidth 参数为 ArgumentOutOfRangeException 在不关心控制台大小为零的代码路径中。

    :下的行为相同 MS点网 单声道

    当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/xamarinstudio的经验来看是这样。

    相关的 :

        3
  •  3
  •   Julo    8 年前

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

    1. 在控制台中一切正常。

    2. 例如

      type input_file.txt | application.exe (英寸 ) ,或 application.exe <input_file.txt

      (替换 type 具有 cat 在里面 )

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

      type input_file.txt | application.exe | grep pattern application.exe <input_file.txt >output_file.txt

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

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

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

      e、 g.从GUI应用程序 (控制台完全不可见)

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

    Console.WindowHeight Console.WindowWidth 在…工作 第一和第二模式的标准方式。在 第2和第3模式的返回值为 . 因此,在Linux中,您无法检测到仅输入重定向。

    IOException 阅读时 只有在有 无输出 安慰 而且只为 窗户 .

    输入 (英寸 窗户 (仅限) 使用此功能:

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

    对于所有其他重定向和操作系统。。。试着试验如何检测它们。不同的控制台属性和功能“工作” 对于不同的模式。

    测试日期 Windows 7 .NET Framework 4 Client Profile Mono JIT compiler version 4.2.1 (Debian 4.2.1.102+dfsg2-7ubuntu4) .

    在Linux中,不要将此函数用于输入重定向 ,因为当您错误地期望重定向而重定向未处于活动状态时,它会导致更多的问题。

        4
  •  1
  •   nqfe    9 年前
    推荐文章