簡體   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