• 0

[C#] Output command line app progress bar to textbox on one line


Question

I got a program that I'd like to output to a textbox but I'm having an issue with the progress bar. All the stdout from the app displays correctly except once I get to a progress bar:


00
00
00
01
01
01
02
02
02
etc...
[/CODE]

I made this code to handle it:

[CODE]
string o = "";
string pattern = @"(\d{1,2}\%)";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
while (!process.HasExited)
{
StringBuilder output = new StringBuilder(process.StandardOutput.ReadLine());
MatchCollection matches = rgx.Matches(o);
if (output.ToString () != o){
if (matches.Count > 0)
{
this.txtOutputLog.AppendText(output + System.Environment.NewLine);
}
else
{
this.txtOutputLog.AppendText(output + System.Environment.NewLine);
}
Application.DoEvents();
}
o = output.ToString();
}
[/CODE]

but still get this:

[CODE]
01
02
03
04
05
[/CODE]

How can I get the progress bar to print on one line? I've also tried using "\r".

21 answers to this question

Recommended Posts

  • 0

AppendText, as its name suggests, adds text after whatever existing text is already there. What you're trying to do if I understand well is to replace existing text (the progress indicator) with new text. For this purpose, you could take the existing text, extract everything but the last 2 characters (with String.Substring), add the 2 replacement characters to the resulting string, and set the textbox's Text value to this new string.

  • 0

Right, I was using AppendText to read the output in real time, line by line. I didn't know what code to use to replace the last line (progress bar). I can get a progress bar on the one line but need to keep all the other output as well.

ie. simple setting this.txtOutputLog.Text = (output); works but won't keep the previous output.

this.txtOutputLog.Text += (output); looks weird and also setting this.txtOutputLog.Text += messes with the textbox focus.

  • 0

something like

txtbox.Text = txtbox.Text.Substring(0, txtbox.Text.Length - 2);
txtbox.AppendText(newCounterValue);
[/CODE]

Substring allows to select which part of a string you want, you can use it to select everything except the characters you want to replace and add the replacement characters after that.

  • 0
  On 13/04/2013 at 00:37, Dr_Asik said:

something like

txtbox.Text = txtbox.Text.Substring(0, txtbox.Text.Length - 2);
txtbox.AppendText(newCounterValue);
[/CODE]

Substring allows to select which part of a string you want, you can use it to select everything except the characters you want to replace and add the replacement characters after that.

This seems to work OK

[CODE]
this.txtOutputLog.Text = this.txtOutputLog.Text.Substring(0, this.txtOutputLog.Text.Length - 11);
this.txtOutputLog.AppendText(o);
[/CODE]

Textbox seems to flicker slightly...

  • 0

You don't need a background worker to use a progress bar any more than to use a textbox. What you need a background worker for is having your long-running operation not block the UI thread so the application remains responsive.

  • 0
  On 13/04/2013 at 01:03, DPyro said:

Ya I was thinking about doing that but would need to figure out how to add the background worker etc.

Could just use the Application.DoEvents() function to do your updates to a progress bar without a background worker. This will stop the gui from locking, but you won't need to use a Background worker.. which is really just a thread with training wheels.

  • 0
  On 13/04/2013 at 01:16, firey said:

Could just use the Application.DoEvents() function to do your updates to a progress bar without a background worker. This will stop the gui from locking, but you won't need to use a Background worker.. which is really just a thread with training wheels.

With easy options like BackgroundWorker (.NET 2) and async in C# (C# 5) now there's really no reason to use DoEvents() anymore, which is an error-prone hack. It may be easy to write, but it's hell to debug. The UI thread is for the UI, using it to perform long-running operations is just bad design.
  • 0

This is all just standard string manipulation, I suggest you take a look at the String class, specifically methods like Trim, Substring, Replace, Concat, Join and Split. For instance here you could store the last entry you added in a temporary string and do a Replace of that with the new one you want. Or you could split by newline characters, exclude the last line, join the result and add the replacement at the end. There are many ways to go about this.

  • 0
  On 13/04/2013 at 01:29, Dr_Asik said:

With easy options like BackgroundWorker (.NET 2) and async in C# (C# 5) now there's really no reason to use DoEvents() anymore, which is an error-prone hack. It may be easy to write, but it's hell to debug. The UI thread is for the UI, using it to perform long-running operations is just bad design.

While I agree with that, it would be a working hack he could use without learning bw's and async stuff.

  • 0

TextBox isn't a very good control to use for console output. It looks like what you're trying to do is simulate a console to display the output from a CLI application you're running in a process. I would recommend using a ListBox instead. You can use the ListBox.Items.Add() method to add each line as it's output then when you get to your progress parsing you can use

ListBox.Items[ListBox.Items.Count - 1] = "<whatever you want>";

to replace the line with the new value. Then only that particular line might flicker. :)

Your second problem is a regular expression issue. If the CLI app's output is different you'd have to match it differently as well. Match(@"(\d+)%.*" ) should get you just the percentage number from your example.

  • 0

Ok the listbox works good but as you said it does flicker quite a bit.

EDIT:

I added this to select the last line which gets rid of the flicker, but how do I change the selected color so that you can't tell it's selected


lstOutputLog.SelectedIndex = lstOutputLog.Items.Count - 1;
[/CODE]

Edited by DPyro
  • 0

Should be clear that I'm replacing:


lstOutputLog.Refresh();
[/CODE]

With:

[CODE]
lstOutputLog.SelectedIndex = lstOutputLog.Items.Count - 1;
[/CODE]

Unless there's a better way to update the listbox after each line is added...

  • 0

You don't need to select anything. You can just change the last line in the Listbox with the code I posted. It will make the last line say "<whatever you want>" the way it is so you would want to use the percentage that you parsed from the process's output instead of the example string. After it doesn't match anymore (i.e.: the process is complete) you can continue logging whatever else it might print using the listbox's Add() method.

  • 0
  On 14/04/2013 at 03:05, GreyWolf said:

You don't need to select anything. You can just change the last line in the Listbox with the code I posted. It will make the last line say "<whatever you want>" the way it is so you would want to use the percentage that you parsed from the process's output instead of the example string. After it doesn't match anymore (i.e.: the process is complete) you can continue logging whatever else it might print using the listbox's Add() method.

This is what I have, but if I don't refresh the listbox somehow then nothing is displayed until the process has ended.


while (!process.HasExited)
{
string pattern = @"(\d+)%.*";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
StringBuilder output = new StringBuilder(process.StandardOutput.ReadLine());
Match Match = rgx.Match(output.ToString ());
if (!Match.Success)
{
lstOutputLog.Items.Add(output + "\n");
}
else
{
lstOutputLog.Items[lstOutputLog.Items.Count - 1] = (output);
}
}
[/CODE]

The other issue I'm having is that the output freezes every couple of seconds. Think it has something to do with the buffer being filled up and waiting to be flushed. :/

  • 0
  On 14/04/2013 at 05:41, DPyro said:

The other issue I'm having is that the output freezes every couple of seconds. Think it has something to do with the buffer being filled up and waiting to be flushed. :/

So I added this to the cli program which is written in c/c++, which fixes the freezing of stdout


setvbuf(stdout, NULL, _IONBF, 0);
[/CODE]

Only issue I have is that I have to set

[CODE]lstOutputLog.SelectionMode = SelectionMode.One;[/CODE]

at the beginning and

[CODE]lstOutputLog.SelectionMode = SelectionMode.None;[/CODE]

at the end so that the listbox isn't selectable. At the end of program run, the log scrolls back to the top :wacko:

  • 0
  On 14/04/2013 at 05:41, DPyro said:

This is what I have, but if I don't refresh the listbox somehow then nothing is displayed until the process has ended.

That's normal, because you're keeping the UI thread busy doing your loop, it cannot do anything else during that. It cannot even repaint itself. That's why the UI thread is for updating the UI and responding to user events, not performing your long-running computations.

There are different ways to go about fixing this. The classical, most correct way is to spawn a background thread; there many tutorials with full code on how to do this, example: this.

Alternatively, you could still do this on the UI thread, but one small part at a time, for instance by passing what forms the body of your while loop to a timer. This will cause this code to execute repeatedly, but will let the UI execute as it wishes between each two calls.

There's as also, as firey pointed out, a hack that consists of calling Application.DoEvents() in your loop; this effectively triggers a full UI update from the currently executing UI update; as long it doesn't end up calling back into your code, it shouldn't lead to horrifying things. Note the use of conditionals there; this isn't a reliable way, which can cause your app to randomly behave in ways you don't understand. I don't recommend this approach unless you really know what you're doing (and if you did you'd probably never choose this approach).

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Offering real value takes effort. It's far more efficient to create a fake crisis, sell the Band-Aid, and host a keynote about how you're saving the world.
    • Windows 11 gets a new way to fix boot issues, Widgets improvements, more in build 26200.5622 by Taras Buria Microsoft is kicking off this week with a duo of new Windows 11 preview builds. Those in the Dev Channel received build 26200.5622 (KB5058512), which introduces several improvements and new features, including a new way to recover from boot issues, widget improvements, new features for Click to Do, and more. Users with Copilot+ PCs can now try a new Click to Do feature. It lets you click a sentence in an email or any other portion of text on your screen and click "Draft with Copilot in Word" to create a document based on the selected text and your instructions. Note that this feature requires a Microsoft 365 subscription. Also, Click to Do now supports French and Spanish languages for the rewriting tool, and text actions are now available in German, Italian, and Portuguese. Next is the big one. Quick Machine Recovery now has its own section in the Settings app. Announced at Ignite 2024, this feature lets you quickly resolve boot issues by applying fixes and patches within the Windows Recovery Environment. The new page enables you to check and configure the status of QMR. Windows Insiders can try QMR in action with test mode. Windows Widgets now feature multiple boards, allowing you to switch between widget-only view and a mix of widgets and news. Other changes include the following: The "Open with" dialog now displays app recommendations, allowing you to discover more apps that support the selected file. Phone Link now groups notifications in the start menu and lets you initiate screen mirroring (Android-only) with a single click. Connected iPhones can also display memories and recently synced photos. The Settings app now has a better alignment for the search bar on Copilot+ PCs, redesigned dialogs for entering your product key, troubleshooting activation, phone activation, and retail demo to match the Windows 11 visuals. Also, there is now a new Device Card for the Home page where you can see a brief rundown of your PC's specs. Now, here is what was fixed (these fixes are rolling out gradually): The following fixes are rolling out for improved Windows Search on Copilot+ PCs: Fixed an underlying crash causing semantic indexing to not work for some Insiders in the last couple flights. [Start menu] There have been some underlying improvements which should help address the issue where clicking your profile picture wasn’t opening the Account Manager for some Insiders after the latest flights. If you’re continuing to experience issues, please file feedback. Fixed an issue causing Start menu to crash on launch for some Insiders in the latest flights. [File Explorer] Fixed an issue where if you opened the “…” menu in the File Explorer address bar to show the full list of folders for the current path, the dropdown might be cut off and the bottom of it inaccessible. Fixed an issue which was causing File Explorer to crash doing various actions in the latest flights, including when deleting files for some Insiders. Fixed an issue where the recommended section in File Explorer wasn’t expanding when using the right arrow key. Fixed an issue which could lead to duplicate access keys in the File Explorer context menu. The following are fixes for AI actions in File Explorer: Fixed the issue where the action result canvas displayed text from left to right for AI actions for Microsoft 365 files w [Task Manager] Fixed an issue where after adding the new CPU Utility column, you might notice that System Idle Process always showed as 0. Fixed an issue where the CPU graphs in the Performance page were still using the old CPU utility calculations. [Narrator] Fixed an issue where the Describe image feature of narrator wasn’t working. [Voice Access] Fixed an issue where support for more descriptive and flexible language on Copilot+ PCs wasn’t working as expected. [Settings] Fixed an underlying issue related to Bluetooth which could cause Settings or Quick Settings to crash on launch for some people. Fixed an issue with Quick Settings where if you clicked the top third of the buttons in the top row, it wouldn’t work. [Other] Fixed an issue with msftedit.dll which was causing apps like Sticky Notes and Dxdiag to crash in certain cases for people using Hebrew or Arabic display languages. And there is a single fix that is available for everyone in the Dev Channel: [General] We have mitigated the issue where if Virtualization Based Security is enabled, applications dependent on virtualization, such as VMware Workstation, would lose the ability to run unless the “Windows Hypervisor Platform” Windows optional component is installed on the system. Finally, here is the list of known bugs: [General] After you do a PC reset under Settings > System > Recovery, your build version may incorrectly show as Build 26100 instead of Build 26200. This will not prevent you from getting future Dev Channel updates, which will resolve this issue. The option to reset your PC under Settings > System > Recovery will not work on this build. [Xbox Controllers] Some Insiders are experiencing an issue where using their Xbox Controller via Bluetooth is causing their PC to bugcheck. Here is how to resolve the issue. Open Device Manager by searching for it via the search box on your taskbar. Once Device Manager is open, click on “View” and then “Devices by Driver”. Find the driver named “oemXXX.inf (XboxGameControllerDriver.inf)” where the “XXX” will be a specific number on your PC. Right-click on that driver and click “Uninstall”. [Click to Do (Preview)] The following known issues will be fixed in future updates to Windows Insiders: Windows Insiders on AMD or Intel™-powered Copilot+ PCs may experience long wait times on the first attempt to perform intelligent text actions in Click to Do after a new build or model update. [Improved Windows Search] [REMINDER] For improved Windows Search on Copilot+ PCs, it is recommended that you plug in your Copilot+ PC for the initial search indexing to get completed. You can check your search indexing status under Settings > Privacy & security > Searching Windows. [Taskbar & System Tray] [NEW] In some cases, taskbar icons may appear small even though the setting to show smaller taskbar buttons is configured as “never”. [File Explorer] The following are known issues for AI actions in File Explorer: Narrator scan mode may not work properly in the action result canvas window for the Summarize AI action for Microsoft 365 files when reading bulleted lists. As a workaround, you can use Caps + Right key to navigate. [Widgets] Until we complete support for pinning in the new widgets board experience, pinning reverts you back to the previous experience. [Graphics] [NEW] When connecting your PC to some older Dolby Vision displays, in some cases you might see severe discoloration. You can navigate to Settings > System > Display > HDR turn off “Use Dolby Vision mode” as a workaround to resolve the issue or disconnect the display. You can find the announcement post on the official Windows Blogs website.
    • Photo Variants 2.2 by Razvan Serea Photo Variants is an all-in-one photo editor for Windows. Quickly cull, import, and edit your images with powerful tools. Enjoy full layer support, precise retouching features, and a wide range of filters and color adjustments. Create multiple versions of a photo instantly with presets, or design from scratch using vector graphics and advanced editing options. Free for personal and commercial use. Photo Variants key Features: Advanced Adjustment Tools: Provides precise control over image modifications. ​ Extensive Filter Collection: Offers over 99 photo filters to apply various effects. ​ Animated Photo Effects: Enables the addition of dynamic elements to images. ​ Automatic Face Retouching: Includes features for enhancing facial features automatically. ​ Support for Multiple Formats: Compatible with over 100 graphic formats, including RAW and PSD files, allowing users to open, edit, and save in these formats. ​ Drawing and Transformation Tools: Facilitates freehand drawing, erasing, filling, cropping, resizing, rotating, and flipping images. Photo Variants supports a wide array of image formats, making it a versatile tool for all your editing needs. Key supported formats include: Raster Formats: .jpeg, .jpg, .png, .bmp, .gif, .tiff, .webp, .ico, .pcx. Camera RAW: .crw, .cr2, .dng, .nef, .raf, .arw, .orf, .x3f, .raw. Professional Formats: .psd, .ai, .svg, .tga, .pdf, .pcl. Specialized Formats: .dicom, .dcm, .heic, .heif, .avif, .exr, .dds. Other: .wmf, .emf, .xps, .jpeg2000 (.jp2)...etc... With support for these formats, Photo Variants offers seamless editing and flexibility for photographers, designers, and creatives. Photo Variants 2.2 changes: Added the ability to save and export all images at once. New option in the RAW import window. Download: Photo Variants 2.2 | 64.2 MB (Freeware) View: Photo Variants Home page | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Something is either premium or not. No such thing as premium lite. They just made fool out of the subscribers who took the lite subscription for some convenience.
    • And not to mention the junk foods, fast foods and processed foods full of chemicals.
  • Recent Achievements

    • Week One Done
      Nullun earned a badge
      Week One Done
    • First Post
      sultangris earned a badge
      First Post
    • Reacting Well
      sultangris earned a badge
      Reacting Well
    • First Post
      ClarkB earned a badge
      First Post
    • Week One Done
      Epaminombas earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      170
    2. 2
      ATLien_0
      125
    3. 3
      snowy owl
      120
    4. 4
      Xenon
      118
    5. 5
      +Edouard
      100
  • Tell a friend

    Love Neowin? Tell a friend!