C#Shell – IO重定向

我正在用C#编写一个替换Windows shell,我目前正在实现的function是将所有IO放在同一个shell窗口中 – 即,不在另一个窗口中打开cmd.exe。

现在,我对输出有部分解决方案。 这是我的代码(其中p是正在运行的进程):

while ( !p.HasExited ) { /* ... - irrelevant */ if ( redirect ) { try { p.BeginOutputReadLine(); } catch { } } } 

该过程设置了所有正确的属性,例如UseShellExecute = FalseRedirectStandard{Input, Output, Error} = True ,并且事件处理程序设置正确,但它不一致。

我已经尝试取出try / catch(我知道这是非常糟糕的做法),并使用繁忙的bool,当处理程序运行时设置为false,但由于某种原因,我仍然在p.BeginOutputReadLine上得到InvalidOperationException( ) – 声明已经存在异步操作。

任何帮助都会受到赞赏,即使它需要与上述解决方案完全不同的解决方案,而不仅仅是修复它。

谢谢。

编辑 :这是启动过程的代码:

 if (redirect) { p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardInput = true; p.StartInfo.UseShellExecute = false; p.OutputDataReceived += new DataReceivedEventHandler(redirectHandler_StdOut); p.ErrorDataReceived += new DataReceivedEventHandler(redirectHandler_StdErr); } p.Start(); 

而且,我意识到我并没有通过不一致来解释我的意思。 正如他们所说,一张图片值得2^3字:

截图

以Begin为前缀的方法通常以异步方式运行。 这是你想要的吗? 因为看起来循环运行得尽可能快,所以调用越来越多的BeginOutputReadLine(因为调用在完成之前立即返回,并且循环在另一次迭代时出现)。

您可以在StandardOutput流上调用ReadLine以获取同步解决方案。 要么:

  while ( !p.HasExited ) { /* ... - irrelevant */ if ( redirect && !busy ) { try { busy = true; p.BeginOutputReadLine(); } catch { } } } ////In the method that gets called upon completion of BeginOutputReadLine busy = false; 

请记住这一点(来自MSDN):

当异步读取操作开始时, 每次关联的进程将一行文本写入其StandardOutput流 ,都会调用事件处理程序。

您可以通过调用CancelOutputRead取消异步读取操作。 读取操作可以由调用者或事件处理程序取消。 取消后,您可以再次调用BeginOutputReadLine以恢复异步读取操作。

这让我相信你应该只调用一次这个方法,它会在写一行时通过回调来通知你。