【发布时间】:2011-09-19 22:34:23
【问题描述】:
在调用第三方命令行工具的 WinForm 应用程序中,有时该工具需要用户输入,例如询问是否应该覆盖文件:
printf("%s already exists, overwrite?: <Y>es, <N>o, <A>ll, <Q>uit?",FName);
for ( ; ; )
switch ( toupper(getch()) ) {
case 'A':
YesToAll=true;
case '\r':
case 'Y':
remove(FName);
return true;
case 0x1B:
case 'Q':
printf("quit\n"); exit(-1);
case 'N':
return false;
}
发生这种情况时,我想在对话框中显示来自printf() 的消息和选项,并将按钮单击重定向为进程的输入。它可能涉及使用System.Diagnostics.Process.StandardInput 发送输入。但是,如果不知道该工具何时需要输入,我将不知道何时在 GUI 中做出相应的反应。当进程处于此 for 循环中时,我的 WinForm 进程将冻结。
编辑:这是通过在另一个线程中启动进程来解锁 UI 的代码,但是我仍然无法读取输出,如果我选择的文件会导致工具询问覆盖选项。 proc_OutputDataReceived(EDIT2: 或 readStdOut 在proc.StandardOutput.BaseStream.BeginRead 的情况下)永远不会被调用,除非该工具不要求输入)。
private BackgroundWorker worker = new BackgroundWorker();
private void fileChosenHandler(object sender, EventArgs e)
{
OpenFileDialog dialog = sender as OpenFileDialog;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(dialog.FileName);
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
string exePath = @"F:\test\test.exe";
Process proc = new Process();
proc.StartInfo.FileName = exePath;
proc.StartInfo.Arguments = "\"" + (string)e.Argument + "\"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
proc.Start();
// method 1: read lines
//proc.BeginOutputReadLine();
// method 2: read characters
proc.StandardOutput.BaseStream.BeginRead(stdOutBuffer, 0, stdOutBuffer.Length, readStdOut, proc);
proc.WaitForExit();
}
private void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
MessageBox.Show("Output: " + e.Data);
}
private byte[] stdOutBuffer = new byte[20];
private void readStdOut(IAsyncResult result)
{
Process proc = result.AsyncState as Process;
int bytesNumber = proc.StandardOutput.BaseStream.EndRead(result);
if (bytesNumber != 0)
{
string text = System.Text.Encoding.ASCII.GetString(stdOutBuffer, 0, bytesNumber);
MessageBox.Show("Output: " + text);
}
// set up the callback again
proc.StandardOutput.BaseStream.BeginRead(stdOutBuffer, 0, stdOutBuffer.Length, readStdOut, proc);
}
知道怎么做吗?谢谢!
【问题讨论】:
标签: c# winforms command-line stdout io-redirection