我想编写一个具有不同行为的控制台应用程序,具体取决于输入是来自键盘还是来自文件。
有可能吗?在C#中最优雅的方法是什么?
答案 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.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时的经验来讲。
相关强>:
答案 2 :(得分:1)
由于框架4.5存在属性Console.IsInputRedirected。 8 - )
请参阅MSDN
https://msdn.microsoft.com/de-de/library/system.console.isinputredirected(v=vs.110).aspx
答案 3 :(得分:1)
标准运行(在控制台中,没有任何重定向)
在控制台中,一切都按预期工作。
使用标准输入和/或标准输出重定向从控制台重定向执行
e.g。
type input_file.txt | application.exe
(在 Windows 中),或application.exe <input_file.txt
用于输入重定向
(将type
替换为 Linux 中的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
用于输入和输出重定向
使用标准输出和错误输出重定向从控制台重定向执行
e.g。 application.exe >output_file.txt 2>error_file.txt
使用隐藏控制台执行并重定向输入/输出/错误
e.g。来自GUI应用程序(控制台根本不可见)
使用隐藏控制台执行不使用重定向输入/输出/错误
这些模式中的每一种都具有自己的功能&#39;。 Console.WindowHeight
和Console.WindowWidth
以标准方式在第一和第二模式的 Windows 中工作。在 Linux 中,第二和第三模式的返回值为零。因此,在Linux中,您无法检测仅重定向的输入。
因此,Lorenz答案的代码不能用于检测所有情况下的重定向。只有在无输出来控制(例如第3种模式)时才会引发IOException
或Console.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 Profile
和Mono JIT compiler version 4.2.1 (Debian 4.2.1.102+dfsg2-7ubuntu4)
上进行了测试。
重要:
不要将此功能用于Linux 中的输入重定向(检测正在运行的操作系统/平台,例如Mono for Windows),因为当您错误地期望重定向并且重定向不活动时会导致更多麻烦