2

我创建了一个子控制台应用程序

_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");
4

2 回答 2

2

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

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

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

当然,既然您已经设置StartInfo.RedirectStandardInputtrue,在幕后 .NET 已经将命令解释器进程的标准输入连接到管道;所以命令解释器只是调用ReadFile(),而不做任何交互式命令行编辑,就像它的标准输入是一个控制台一样。即使您可以找到并打开命令解释器进程控制台的句柄,并为它写一个INPUT_RECORDforTab键,命令解释器仍在读取其标准输入的管道,并忽略其控制台。

如果您希望命令解释器像与控制台对话、命令行编辑等一样工作,您必须使用标准输入作为控制台生成进程,您必须(然后)获得其句柄您可以使用 模拟按键WriteConsoleInput()。这在 .NET 中相当困难。

于 2011-03-01T18:25:18.387 回答
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 在此处的回答,这并不总是有效。

于 2010-03-23T05:26:25.463 回答