Search code examples
c#winformscmdrichtextboxprogress

C# cmd output progress (%) one line


I'm working on a cmd output to RichTextBox. Is there any way to merge/join all the progress (%) into a single line of the RichTextBox? Instead of creating a line for each %. I would like it to be like cmd (except removing the blank lines as it is now).

private async void btnStart_Click(object sender, EventArgs e){
await Task.Factory.StartNew(() =>
{
    Execute1("Prtest.exe", " x mode2 C:\\input.iso C:\\output.iso");
});
}

private void Execute1(string filename, string cmdLine){
var fileName = filename;
var arguments = cmdLine;

var info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = arguments;

info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.CreateNoWindow = true;

using (var p = new Process())
{
    p.StartInfo = info;
    p.EnableRaisingEvents = true;

    p.OutputDataReceived += (s, o) =>
    {
        tConsoleOutput(o.Data);
    };
    p.ErrorDataReceived += (s, o) =>
    {
        tConsoleOutput(o.Data);
    };

    p.Start();
    p.BeginOutputReadLine();
    p.BeginErrorReadLine();
    p.WaitForExit();
}
}

public void tConsoleOutput(string text){
BeginInvoke(new Action(delegate ()
{
    rtConsole.AppendText(text + Environment.NewLine);
    rtConsole.ScrollToCaret();
    //remove empty lines
    rtConsole.Text = Regex.Replace(rtConsole.Text, @"^\s*$(\n|\r|\r\n)", "", RegexOptions.Multiline);
}));
}

Real cmd.exe output:

Processing: 100%

Sectors: 43360

Completed.

C# RichTextBox (rtConsole) output:

Processing: 2%
Processing: 4%
Processing: 7%
Processing: 9%
Processing: 11%
Processing: 14%
Processing: 16%
Processing: 39%
Processing: 100%
Sectors: 43360
Completed.

UPDATE: Solved

enter image description here

Big Thanks @Jackdaw


Solution

  • Try the method below:

    static public void tConsoleOutput(RichTextBox rtb, string line)
    {
        var pattern = @"^Processing: \d{1,3}%.*$";   
        if (!line.EndsWith(Environment.NewLine))
            line += Environment.NewLine;
    
        var isProcessing = Regex.Match(line, pattern).Success;
    
        rtb.Invoke((MethodInvoker)delegate
            {
                var linesCount = rtb.Lines.Length;
                if (linesCount > 1 && isProcessing)
                {
                    var last = rtb.Lines[linesCount - 2];
                    if (Regex.Match(last, pattern).Success)
                    {
                        var nlSize = Environment.NewLine.Length;
                        // Update latest line
                        var sIndex = rtb.GetFirstCharIndexFromLine(linesCount - nlSize);
                        var eIndex = sIndex + last.Length + nlSize;
                        rtb.Select(sIndex, eIndex - sIndex);
                        rtb.SelectedText = line;    
                        return;                                
                    }                
                }
                rtb.AppendText(line);
            });
    }
    

    And seems like that:

    enter image description here