读取管道输入后接收用户输入

时间:2014-02-14 12:45:43

标签: c# .net io console-application stdin

我正在.NET 4中编写一个小型的交互式控制台应用程序。我想扩展它以便能够处理可选的重定向输入,例如:

echo hello | myapp.exe

麻烦当然是重定向输入窃取了“键盘流”,所以对Console.Read *()的任何调用都会返回null。

目前我所拥有的是:

// Read piped input
try
{
    bool keyAvailable = Console.KeyAvailable;
}
catch
{
    string redirected = Console.In.ReadToEnd();
    // Need to do something here to "un-redirect" stdin back to keyboard
}

// Always returns null
String userInput = Console.ReadLine();

在UNIX上我可以打开一个到/ dev / tty的流来获取用户输入,但是如何在Windows上使这个工作?

谢谢!

[编辑]

基于克雷格回答的工作解决方案:

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern bool FreeConsole();

try
{
     bool keyAvailable = Console.KeyAvailable;
}
catch
{
    string redirectedInput = Console.In.ReadToEnd();
    bool freed = FreeConsole();
    bool attached = AttachConsole(-1);
    Console.SetIn(new StreamReader(Console.OpenStandardInput()));
}

我必须首先使用

从控制台中分离
FreeConsole().

我可以选择使用

创建一个全新的控制台
AllocConsole()

但这会创建另一个控制台窗口,我真的不想要。相反,我使用

附加到父控制台(现有的cmd.exe)
AttachConsole(-1) // -1 = "Parent".

我只能推测.NET类控制台保存对前一个stdin流的引用,但只有在调用Console.SetIn()之后Console.ReadLine()才会恢复它的阻塞行为,等待用户输入

现在开始调查如果我使用我的应用程序的stdout重定向运行会发生什么:

echo hello | myapp.exe | somewhere ...

1 个答案:

答案 0 :(得分:1)

AttachConsole函数应该可以完成这项任务,不过我只用它来重新获得输出而不是输入。