将TAB发送到子控制台(窗口)

时间:2009-04-11 15:51:30

标签: .net console tab-completion

我用

创建一个子控制台应用程序
_process = new Process();
_process.StartInfo.FileName = @"cmd.exe";
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.CreateNoWindow = true;

_proccess.Start();

现在我可以去c:\ aaa

_process.StandardInput.Write("cd c:\\aaa\xD\xA");

但通常用户可以输入c:\ + TAB + ENTER。我怎么能这样做?这不起作用:

_process.StandardInput.Write("cd c:\\\0x9\xD\xA");

2 个答案:

答案 0 :(得分:2)

子进程的标准输入与它所附加的控制台之间存在根本区别。交互模式下的命令解释器期望将 与控制台作为标准输入连接到管道/文件,并改变其行为以匹配哪一个认定。对于管道/文件,它只是简单地调用ReadFile()函数。但是,对于控制台,它通过ReadConsoleInput()接收输入,其中非字母数字键可通过其虚拟键代码识别。

有关示例,请参阅ReactOS CMD中的ReadCommand()函数。

如果您将一个值为9的字节写入流程的标准输入管道,那么它将从调用ReadFile()的内容中看到。但它不会将其视为 Tab 按键,因为(对于初学者而言)它不是一个;它只是字节值9来自管道。此外,命令解释程序在交互模式下执行的命令行编辑仅在检测到标准输入是控制台时发生,而不是在管道或文件时发生。命令解释器使用ReadConsoleInput(),它不读取字节缓冲区但读取INPUT_RECORDs的序列;因此,如果希望命令解释程序看到 Tab keypress,则必须WriteConsoleInput()到该控制台处理模拟 Tab 键的INPUT_RECORD在其输入流中。

当然,由于您已将StartInfo.RedirectStandardInput设置为true,因此.NET已将命令解释程序进程的标准输入连接到管道;所以命令解释器只是调用ReadFile(),而不进行任何交互式命令行编辑,就像它的标准输入是控制台一样。即使您可以找到并打开命令解释器进程控制台的句柄,并为其写入INPUT_RECORD Tab 键,命令解释程序也会读取其标准输入的管道,并忽略它的控制台。

如果你想要一个命令解释器就像它与控制台,命令行编辑和所有人一样行动,你必须用<标准输入作为控制台来生成进程,你必须获得它的句柄,以便你可以使用WriteConsoleInput()来模拟按键。这在.NET中相当困难。

答案 1 :(得分:1)

如何深入了解Windows API?

using System.Runtime.InteropServices;
//...
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private const int WM_CHAR = 0x0102;
private const int VK_TAB = 0x9;
private const int VK_RETURN = 0xD;
//...
SendMessage(_process.Handle, WM_CHAR, new IntPtr(VK_TAB), new IntPtr(0));
SendMessage(_process.Handle, WM_CHAR, new IntPtr(VK_RETURN), new IntPtr(0));

然而,根据Kevin Montrose's answer here,这并不总是有效。