为什么不引发 OutputDataReceived 以进行提示,从而阻止发出 AutoResetEvent 信号?
Why is OutputDataReceived not being raised for prompt, preventing AutoResetEvent from being signaled?
我正在制作一个应用程序,它将产生一个具有命令行解释器的进程。我需要从另一台机器向此 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
事件中收到了提示,或者收到的数据为空。 IE。当上一个命令完成并显示提示时,OutputDataReceived
事件没有被引发。
我提供的输入命令确实需要一段时间,但确实完成了。我在这里使用 AutoResetEvent 是不是错了?
如果没有 a good, minimal, complete code example,就不可能确定代码可能出了什么问题。但我可以看到一个明显的解释:
收到的每个 行 输出都会引发 OutputDataReceived
事件。即以换行符结尾的字符串。
没有关于您的外部流程的具体信息,我无法确定。但是大多数 CLI 类型的场景都涉及显示 没有 换行符的提示。 IE。提示被写入控制台,用户输入应该在提示后立即回显到控制台,而不是在下一行。
如果您的情况是这种情况,那么几乎可以肯定您没有检测到提示,因为不会单独针对提示引发事件。在上一个命令操作的最后一行输出之后,下一次将引发事件是 在 命令已通过标准输入发送到进程之后。这显然为时已晚,无法知道何时发送该命令。 :)
要使其正常工作,您将必须通过不是基于行的其他可用机制之一从流程中读取输入。
我正在制作一个应用程序,它将产生一个具有命令行解释器的进程。我需要从另一台机器向此 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
事件中收到了提示,或者收到的数据为空。 IE。当上一个命令完成并显示提示时,OutputDataReceived
事件没有被引发。
我提供的输入命令确实需要一段时间,但确实完成了。我在这里使用 AutoResetEvent 是不是错了?
如果没有 a good, minimal, complete code example,就不可能确定代码可能出了什么问题。但我可以看到一个明显的解释:
收到的每个 行 输出都会引发 OutputDataReceived
事件。即以换行符结尾的字符串。
没有关于您的外部流程的具体信息,我无法确定。但是大多数 CLI 类型的场景都涉及显示 没有 换行符的提示。 IE。提示被写入控制台,用户输入应该在提示后立即回显到控制台,而不是在下一行。
如果您的情况是这种情况,那么几乎可以肯定您没有检测到提示,因为不会单独针对提示引发事件。在上一个命令操作的最后一行输出之后,下一次将引发事件是 在 命令已通过标准输入发送到进程之后。这显然为时已晚,无法知道何时发送该命令。 :)
要使其正常工作,您将必须通过不是基于行的其他可用机制之一从流程中读取输入。