C#Shell – IO重定向
我正在用C#编写一个替换Windows shell,我目前正在实现的function是将所有IO放在同一个shell窗口中 – 即,不在另一个窗口中打开cmd.exe。
现在,我对输出有部分解决方案。 这是我的代码(其中p是正在运行的进程):
while ( !p.HasExited ) { /* ... - irrelevant */ if ( redirect ) { try { p.BeginOutputReadLine(); } catch { } } }
该过程设置了所有正确的属性,例如UseShellExecute
= False
, RedirectStandard{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以恢复异步读取操作。
这让我相信你应该只调用一次这个方法,它会在写一行时通过回调来通知你。