2

我正在制作一个应用程序,它将产生一个具有命令行解释器的进程。我需要从另一台机器向这个 CLI 提供命令。现在,我必须检测命令何时完成,因此我正在检查 CLI 的提示符何时出现在我正在生成的进程的标准输出中。这是一段代码:

private string StartProcess(string input)
{
try
{
    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    AutoResetEvent commandFinished = new AutoResetEvent(false);

    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
        FileName = "myprocess.exe",
        Arguments = "",
        UseShellExecute = false,
        CreateNoWindow = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        RedirectStandardInput = true,
        UserName = System.Environment.UserName
    };

    Process myProcess = new Process()
    {
        StartInfo = startInfo,
        EnableRaisingEvents = true
    };

    myProcess.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
    {
        if (e.Data != null)
        {
            string prompt = "user >";

            if (e.Data.Substring(e.Data.Length - prompt.Length).Equals(prompt))
            {
                Console.WriteLine("Received prompt! Sending CommandFinished signal!");
                commandFinished.Set();
                Console.WriteLine("CommandFinished signal set!");
            }
            else
            {
                output.AppendLine(e.Data);
            }
        }
        else
        {
            // Data finished
            Console.WriteLine("StdOut data finished! Sending CommandFinished signal!");
            commandFinished.Set();
            Console.WriteLine("CommandFinished signal set!");
        }
    });


    myProcess.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
    {
        if (e.Data != null)
        {
            Console.WriteLine("Error Data received: " + e.Data.ToString());
            error.AppendLine(e.Data);
        }
    });

    myProcess.Start();
    myProcess.BeginOutputReadLine();
    myProcess.BeginErrorReadLine();

    Console.WriteLine("Executing input command: " + input);
    myProcess.StandardInput.WriteLine(input);

    Console.WriteLine("Waiting for input command to complete...");

    commandFinished.WaitOne();

    Console.WriteLine("Command complete!");

    return output.ToString();
}
catch (Exception ex)
{
    Console.WriteLine("EXCEPTION: " + ex.ToString());
    throw ex;
}
}

现在,代码挂在对 WaitOne() 的调用上。我很困惑为什么 - 我没有在输出中检测到 CLI 提示,而且我从来没有收到任何 WriteLines 告诉我在OutputDataReceived事件中收到了提示,或者收到的数据为空。即,OutputDataReceived当上一个命令完成并显示提示时,没有引发事件。

我提供的输入命令确实需要一段时间,但它确实完成了。我在这里使用 AutoResetEvent 错了吗?

4

1 回答 1

2

如果没有一个好的、最小的完整的代码示例,就不可能确定代码可能出了什么问题。但我可以看到一个明显的解释:

为接收到的OutputDataReceived每一输出引发事件。即,由换行符终止的字符串。

如果没有有关您的外部流程的详细信息,我不能肯定地说。但是大多数 CLI 类型的场景都涉及显示没有换行符的提示。即提示被写入控制台,用户输入应在提示之后立即回显到控制台,而不是在下一行。

如果您的场景是这种情况,那么几乎可以肯定您无法检测到提示,因为不会仅针对提示引发事件。在上一个命令操作的最后一行输出之后,下一次引发事件是命令通过标准输入发送到进程之后。这显然为时已晚,无法知道何时发送该命令。:)

要使其正常工作,您必须通过其他可用的基于行的机制之一从进程中读取输入。

于 2015-10-29T23:01:57.847 回答