我正在使用在后台运行cmd的winform,异步重定向输入和输出。
目前,winform迭代一系列命令,通过StreamWriter将每个命令写入cmd,将StandardInput重定向到。如何强制循环等到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.
}
}
}
答案 0 :(得分:1)
我认为没有任何内置可以支持这一点。但是你可以发送自己的特殊命令,然后等到你在输出中看到这个,例如, 类似的东西:
const string Separator= "---Command Completed--\xE3\xE2\xE1\xE0\xE3";
// Has to be something that won't occur in normal output.
volatile bool finished = false;
private void button1_Click(object sender, EventArgs e)
{
foreach (string command in _commands)
Run(command);
}
private void writeToConsole(string output)
{
if (output.IndexOf(Separator) >= 0)
finished = true;
else
richTextBox1.AppendText(output);
}
private void Run(string command)
{
finished = false;
_process.StandardInput.WriteLine(command);
_process.StandardInput.WriteLine("@echo " + Seperator);
while (!finished)
{
Application.DoEvents();
System.Threading.Thread.Sleep(100);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
finished = true;
}
答案 1 :(得分:0)
假设您正在使用System.Diagnostics.Process,那么您可能需要类似
的内容ProcessStartInfo pi = new ProcessStartInfo(cmd);
pi.Arguments = ...
pi.WorkingDirectory = ...
Process myProcess = Process.Start(pi);
myProcess.WaitForExit();
答案 2 :(得分:0)
我最终解决了这个问题,将我与命令提示符的交互包装到一个单独的类中,而不是为所有操作维护一个提示,我为每个调用启动了另一个提示。然后我利用WaitForExit()
来同步我的线程。
在每个命令之后,我用exit
命令写入关闭进程。我扫描输出以进行退出调用,当我找到一个时,我使用该行的上下文来保存工作空间,以便从同一个工作目录提示下一个命令。在将EventHandlers转发给winform之前,我还必须连接一个DataRecievedEventHandler来解析头和退出调用。
关于这个解决方案让我烦恼的是,如果我正在运行的任何进程的输出打印出exit
,输出扫描程序将表现得好像它找到了原始出口。我使用了sgmoore在他的答案中使用的相同解决方案 - 我在exit [UNIQUE STRING]
写入提示,并扫描输出,但我确信这远非最佳实践。