Home > Enterprise >  C# cmd output progress (%) one line
C# cmd output progress (%) one line

Time:02-24

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

CodePudding user response:

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

CodePudding user response:

I don't know about the code that you have written (or, if it's not yours, where it comes from) but I can tell you that the easiest way of doing this is the \r character, which resets your caret to the beginning of the line.

This means that you must make sure not to use Console.WriteLine but Console.Write instead.

An example:

Console.Write("00.00% Done");
Thread.Sleep(1500);
Console.Write("\r100.00% Done");
  • Related