繁体   English   中英

捕获命令行输出(通过字符输出,不必每行等待)

[英]Capture command line output (by character output, not having to wait per line)

我目前正在将命令行过程的输出渲染到文本框中。 问题在于,在正常的命令提示符窗口中,所写的其中一行有一个负载条之类的东西……每隔几秒钟就会输出“。”。 到屏幕上。...经过几个点后,它将开始新的一行,然后继续加载直到完成其过程。

使用以下代码,而不是获取这些“。” 一一出现,我的OutputDataRecieved正在等待整行被写出...所以加载栏没用...也就是说,它等待“ .............”,然后作用于它。

有没有办法跟踪正在输出到屏幕的每个字符,而不是跟踪每行输出的内容?

//Create process
System.Diagnostics.Process process = new System.Diagnostics.Process();

// arguments.ProcessStartInfo contains the following declaration:
// ProcessStartInfo = new ProcessStartInfo( "Cmd.exe" )
// {
//     WorkingDirectory = executableDirectoryName,
//     UseShellExecute = false,
//     RedirectStandardInput = true,
//     RedirectStandardOutput = true,
//     CreateNoWindow = true,
// }
process.StartInfo = arguments.ProcessStartInfo;

//Start the process
StringBuilder sb = new StringBuilder();

bool alreadyThrownExit = false;

// The following event only seems to be run per line output rather than each character rendering the command line process useless
process.OutputDataReceived += ( sender, e ) =>
{
    sb.AppendLine( e.Data );
    CommandLineHelper.commandLineOutput = sb.ToString();
    arguments.DelegateUpdateTextMethod();

    if( !alreadyThrownExit )
    {
        if( process.HasExited )
        { 
            alreadyThrownExit = true;
            arguments.DelegateFinishMethod();
            process.Close();
        }
    }
};

process.Start();
process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );

process.BeginOutputReadLine();

如果要基于每个字符异步处理给定进程的stdout,则可以使用TextReader.ReadAsync()方法。 无需执行处理OutputDataReceived事件的代码,只需执行以下操作:

process.Start();

// Ignore Task object, but make the compiler happy
var _ = ConsumeReader(process.StandardOutput);

process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );

哪里:

async Task ConsumeReader(TextReader reader)
{
    char[] buffer = new char[1];

    while ((await read.ReadAsync(buffer, 0, 1)) > 0)
    {
        // process character...for example:
        Console.Write(buffer[0]);
    }
}

另外,您可以只创建一个专用线程,并使用该线程在循环中调用TextReader.Read()

process.Start();

new Thread(() =>
{
    int ch;

    while ((ch = process.StandardOutput.Read()) >= 0)
    {
        // process character...for example:
        Console.Write((char)ch);
    }
}).Start();

process.StandardInput.WriteLine( arguments.Command );
process.StandardInput.WriteLine( "exit" );

恕我直言,后者效率更高,因为它不需要太多的跨线程同步。 但是前者更类似于您对OutputDataReceived事件使用的事件驱动方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM