等待命令完成
我正在使用一个在后台运行 cmd 的 winform,异步重定向输入和输出。
目前,winform 迭代一系列命令,通过 StandardInput 重定向到的 StreamWriter 将每个命令写入 cmd。如何强制循环等待 cmd 中当前命令完成后再写入下一行?
编辑:我取出了所有实际的项目代码,并将其替换为这个,这是我正在尝试做的事情的精简版本,仅包括与我的问题相关的项目组件。
public partial class Form1 : Form
{
public delegate void WriteToConsoleMethod(string text);
Process _process;
string[] _commands =
{
"echo hello world",
"echo my name is T.K.",
"echo Here is a list of commands"
};
public Form1()
{
InitializeComponent();
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd")
{
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
_process = Process.Start(processStartInfo);
_process.OutputDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
_process.ErrorDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
_process.BeginErrorReadLine();
_process.BeginOutputReadLine();
}
private void DataReceived_EventHandler(object sender, DataReceivedEventArgs e)
{
IAsyncResult result = this.BeginInvoke(new WriteToConsoleMethod(writeToConsole), new object[] { e.Data + Environment.NewLine });
this.EndInvoke(result);
}
private void writeToConsole(string output)
{
txtbxConsole.AppendText(output);
}
private void btnBegin_Click(object sender, EventArgs e)
{
foreach (string command in _commands)
{
_process.StandardInput.WriteLine(command);
// I want a way to pause here until the cmd has finished processing the command.
}
}
}
I am working with a winform that runs a cmd in the background, redirecting input and output asynchronously.
Currently, the winform iterating through an array of commands, writing each to the cmd via the StreamWriter the StandardInput is redirected to. How can I force the loop to wait until the present command is complete in the cmd before writing the next line in?
EDIT: I took out all of my actual project code, and replaced it with this, a stripped down version of what I'm trying to do, only including components of my project relevant to my question.
public partial class Form1 : Form
{
public delegate void WriteToConsoleMethod(string text);
Process _process;
string[] _commands =
{
"echo hello world",
"echo my name is T.K.",
"echo Here is a list of commands"
};
public Form1()
{
InitializeComponent();
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd")
{
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
_process = Process.Start(processStartInfo);
_process.OutputDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
_process.ErrorDataReceived += new DataReceivedEventHandler(new DataReceivedEventHandler(DataReceived_EventHandler));
_process.BeginErrorReadLine();
_process.BeginOutputReadLine();
}
private void DataReceived_EventHandler(object sender, DataReceivedEventArgs e)
{
IAsyncResult result = this.BeginInvoke(new WriteToConsoleMethod(writeToConsole), new object[] { e.Data + Environment.NewLine });
this.EndInvoke(result);
}
private void writeToConsole(string output)
{
txtbxConsole.AppendText(output);
}
private void btnBegin_Click(object sender, EventArgs e)
{
foreach (string command in _commands)
{
_process.StandardInput.WriteLine(command);
// I want a way to pause here until the cmd has finished processing the command.
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为没有任何内置的东西可以支持这一点。但是,您可以发送自己的特殊命令,然后等到您在输出中看到此命令,例如,
类似的东西:
I don't think there is anything built-in that will support that. However you could send your own special command and then wait until you see this in the output for example ,
something like :
假设您正在使用 System.Diagnostics.Process,那么您可能需要类似的东西
Assuming you are using System.Diagnostics.Process, then you probably need something like
我最终通过将与命令提示符的交互包装到一个单独的类中来解决这个问题,并且我没有为所有操作维护一个提示,而是为每个调用启动另一个提示。然后我利用
WaitForExit()
来同步我的线程。在每个命令之后,我都会写入一个
exit
命令来关闭该进程。我扫描输出中的退出调用,当找到退出调用时,我使用该行的上下文来保存工作区,以便从同一工作目录发出下一个命令的提示。在将 EventHandler 转发到 winform 之前,我还必须连接 DataRecievedEventHandler 来解析标头并退出调用。这个解决方案让我烦恼的是,如果我正在运行的任何进程的输出打印出
exit
,输出扫描器的行为就像它找到了原始出口一样。我采用了 sgmoore 在他的回答中使用的相同解决方案 - 我在提示中写入退出 [UNIQUE STRING] 并扫描输出,但我确信这远非最佳实践。I ended up solving this problem by wrapping my interaction with the command prompt into a separate class and instead of maintaining one prompt for all of the actions, I started up another prompt for each call. Then I take advantage of
WaitForExit()
to synchronize my threads.After each command, I write in an
exit
command to close the process. I scan the output for exit calls, and when I find one, I use the context of that line to save the workspace so that the prompt for the next command will be made from the same working directory. I also had to hook up a DataRecievedEventHandler to parse out the header and exit calls before forwarding the EventHandlers to the winform.The thing that's nagging me about this solution is that if the output of whatever process I'm running prints out
exit
, output scanner will behave as though it found the original exit. I employed the same solution sgmoore had in his answer - I write inexit [UNIQUE STRING]
to the prompt, and scan the output for that, but I'm sure that's far from best practice.