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

jpb*_*chi 25 c# console redirect stdin

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

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

Han*_*ant 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);
}
Run Code Online (Sandbox Code Playgroud)

用法:

bool inputRedirected = ConsoleEx.IsInputRedirected;
Run Code Online (Sandbox Code Playgroud)

更新:这些方法已添加到.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

  • 上面的代码适用于.NET 4.5,现在包含属性IsErrorRedirected,IsInputRedirected和IsOutputRedirected. (3认同)

Lor*_*uer 5

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

Crossplatform:在Linux和Windows上的MS dotNETMono下的行为是相同的(我还没有在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; }
        }
}
Run Code Online (Sandbox Code Playgroud)

2016年更新:为IsConsoleSizeZero代码添加了异常处理,以在更广泛的环境中提高代码的可用性.

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

相关: