如何检测 Console.In (stdin) 是不是已被重定向?
Posted
技术标签:
【中文标题】如何检测 Console.In (stdin) 是不是已被重定向?【英文标题】:How to detect if Console.In (stdin) has been redirected?如何检测 Console.In (stdin) 是否已被重定向? 【发布时间】:2011-03-28 01:30:30 【问题描述】:我想编写一个具有不同行为的控制台应用程序,具体取决于输入是来自键盘还是来自文件。
有可能吗?在 C# 中最优雅的方式是什么?
【问题讨论】:
【参考方案1】:您可以通过 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
【讨论】:
上面的代码适用于 .NET 4.5,现在包括属性 IsErrorRedirected、IsInputRedirected 和 IsOutputRedirected。 有趣的实现,可惜不适用于跨平台开发。 isatty() 函数往往可以在其他平台上进行类似的测试。【参考方案2】:有趣的是,当管道打开时,System.Console.WindowHeight
和System.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 的经验来看。
相关:
MSDN:KeyAvailable
Setting System.Console.WindowHeight throws an System.NotSupportedException under Mono.
【讨论】:
Console.WindowHeight
不错!不过,我不太确定Console.KeyAvailable
的使用。一方面,完全可以同时重定向输入和输出,而您的代码将无法检测到这一点。
我在 Debian Wheezy 上运行。 0 == (Console.WindowHeight + Console.WindowWidth) 技巧对我有用。例如,当我的应用程序通过 monit 启动时,总和为 0。当从命令提示符手动启动时,它是一个正数。无控制台运行时,KeyAvailable 返回 false,但如果我实际调用 ReadKey,则返回零。
我可以确认这似乎适用于 Mac。虽然 Mono 在 Xamarin Studio 中报告“警告:Mono LIMITATION: Only works on windows”。我不知道“Windows”是否拼写错误(大写 W),或者错误是说它在调试器中不起作用。
这段代码不安全,Console.KeyAvailable 在某些情况下当输入被重定向时会抛出 InvalidOperationException —— 所以仅仅检查该属性可能会使应用程序崩溃【参考方案3】:
Lorenz 的回答是一个好的开始,可惜只能作为一个灵感。运行控制台应用程序的模式更多。
标准运行(在控制台中,没有任何重定向)
在控制台中一切正常。
使用标准输入和/或标准输出重定向从控制台执行重定向
例如
type input_file.txt | application.exe
(在 Windows 中),或 application.exe <input_file.txt
用于输入重定向
(在 Linux 中将 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
用于输入和输出重定向
从带有标准输出的控制台重定向执行和错误输出重定向
例如application.exe >output_file.txt 2>error_file.txt
使用隐藏控制台执行并重定向输入/输出/错误
例如来自 GUI 应用程序(控制台根本不可见)
使用隐藏控制台执行没有输入/输出/错误重定向
每种模式都有自己的“功能”。 Console.WindowHeight
和 Console.WindowWidth
在 Windows 中以标准方式用于第一和第二模式。在 Linux 中,第 2 和第 3 模式的返回值是 0。因此,在 Linux 中,您不能仅检测输入重定向。
因此,Lorenz answer 中的代码不能在所有情况下都用于检测重定向。读取Console.WindowHeight
或Console.WindowWidth
时的IOException
仅在(例如第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 Profile
和Mono JIT compiler version 4.2.1 (Debian 4.2.1.102+dfsg2-7ubuntu4)
上测试。
重要提示:
不要在 Linux 中使用此功能进行输入重定向(检测正在运行的操作系统/平台,例如 Windows 的 Mono),因为当您错误地期望重定向并且重定向未激活时,它可能会导致更多麻烦.
【讨论】:
这是迄今为止唯一对我有用的解决方案。 .NET Core 3.1 使用 C#。谢谢!【参考方案4】:由于框架 4.5 存在属性 Console.IsInputRedirected。 8-)
请参阅 Microsoft Docs:https://docs.microsoft.com/en-us/dotnet/api/system.console.isinputredirected
【讨论】:
也适用于 .NET 5 和 6,这非常好。谢谢!以上是关于如何检测 Console.In (stdin) 是不是已被重定向?的主要内容,如果未能解决你的问题,请参考以下文章
你遇到过VMware Remote Console Plug-in安装问题??