我使用Process类从.NET程序运行cmd.exe,并传入各种命令来执行程序,例如ipconfig,netstat等。问题是有时这些程序输出错误文本,这些文本被发送到StandardError,但在标准输出过程中无法确切知道错误被打印到哪里。我得到的只是单独的错误消息。有没有可能将StandardOutput和StandardError合并到一个同步流中,这样我就可以获得所有的数据?如果不是,那么我如何组织来自两个不同流的输出,使其按正确的顺序排列?
发布于 2015-04-23 20:24:44
井。我猜您不能真的期望STDOUT和STDERR按照它们输出的确切顺序出现。这是因为在系统级,STDOUT和STDERR分别有自己的缓冲区。你可以想象这样的情况-
(1)当'command‘首先写入STDOUT时,可能不会立即刷新缓冲区。
(2)然后'command‘写入STDERR,但是这次STDERR的缓冲区可能会被刷新。
在这种情况下,虽然(1)在前面,但我们最终得到的是(2)在前面。
希望下面的代码片段能有所帮助-
(改进代码)
class OutputContext
{
public const int BufferSize = 1024;
public bool IsEof { get; set; }
public bool IsWaiting { get; set; }
public byte[] Buffer { get; set; }
public StreamReader Reader { get; set; }
public object Tag { get; set; }
public OutputContext(StreamReader r, object tag)
{
IsEof = false;
IsWaiting = false;
Buffer = new byte[BufferSize];
Reader = r;
Tag = tag;
}
}
Process proc;
void Callback(IAsyncResult ar)
{
lock (ar.AsyncState)
{
OutputContext ctx = ar.AsyncState as OutputContext;
int c = ctx.Reader.BaseStream.EndRead(ar);
ctx.IsWaiting = false;
if (c == 0)
{
ctx.IsEof = true;
return;
}
string content = Encoding.UTF8.GetString(ctx.Buffer, 0, c);
Console.Write(content);
Console.Out.Flush();
}
}
void RedirectOutput(OutputContext ctx)
{
lock (ctx)
{
if (ctx.IsEof)
{
return;
}
if (ctx.IsWaiting)
{
return;
}
ctx.IsWaiting = true;
IAsyncResult ar = ctx.Reader.BaseStream.BeginRead(ctx.Buffer, 0,
OutputContext.BufferSize, Callback, ctx);
}
}
void Run(string yourprog, string yourargs)
{
// If this is a GUI app, this shall not be run on the UI thread.
// Spin a new thread to handle it and wait for the thread to complete.
// And you can always accept the input as long as the UI thread is not
// blocked, and redirect the input to the target proc's stdin asycly.
proc = new Process();
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.FileName = yourprog;
proc.StartInfo.Arguments = yourargs;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
OutputContext stdoutCtx = new OutputContext(proc.StandardOutput, "STDOUT");
OutputContext stderrCtx = new OutputContext(proc.StandardError, "STDERR");
while (!stdoutCtx.IsEof && !stderrCtx.IsEof)
{
RedirectOutput(stdoutCtx);
RedirectOutput(stderrCtx);
}
proc.WaitForExit();
}
}https://stackoverflow.com/questions/29818035
复制相似问题