Click here to Skip to main content
15,791,050 members
Articles / Programming Languages / C#
Tip/Trick

A Console Progress Bar in C#

Rate me:
Please Sign up or sign in to vote.
4.95/5 (27 votes)
6 Jan 2020MIT1 min read 51K   1K   42   35
Easily add progress reporting to your console apps

ProgressDemo

Introduction

I write a lot of console apps, often tools and utilities that generate source code and other files. Sometimes, this generation can take some time and it would be nice to be able to report progress to the user.

I've seen a lot of progress bars for Winforms and WPF but not much of anything for the console, and yet it strikes me as something pretty useful.

Using this Mess

You can call ConsoleUtility.WriteProgressBar() to report a progress with a known amount of work to be done, or ConsoleUtility.WriteProgress() to report a progress with an unknown amount of work to be done. The first parameter in any case is the progress. For the open ended progress (WriteProgress()), the first parameter is simply an integer value that gets incremented each time. For the bar, it's a number between 0 and 100, inclusive. The second parameter should be false the first time the method is called, and true for subsequent times. This demo code should demonstrate:

C#
ConsoleUtility.WriteProgressBar(0);
for (var i = 0; i <= 100; ++i)
{
    ConsoleUtility.WriteProgressBar(i,true);
    Thread.Sleep(50);
}
Console.WriteLine();
ConsoleUtility.WriteProgress(0);
for (var i = 0; i <= 100; ++i)
{
    ConsoleUtility.WriteProgress(i, true);
    Thread.Sleep(50);
}

Coding this Mess

The code is short and sweet. The only non-intuitive bits are the use of backspace to overwrite our previous progress and the format string we use to pad the percentage with leading spaces.

C#
using System;

namespace CU
{
    static class ConsoleUtility
    {
        const char _block = '■';
        const string _back = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
        const string _twirl = "-\\|/";
        public static void WriteProgressBar(int percent, bool update = false)
        {
            if(update)
                Console.Write(_back);
            Console.Write("[");
            var p = (int)((percent / 10f)+.5f);
            for (var i = 0;i<10;++i)
            {
                if (i >= p)
                    Console.Write(' ');
                else
                    Console.Write(_block);
            }
            Console.Write("] {0,3:##0}%", percent);    
        }
        public static void WriteProgress(int progress, bool update = false)
        {
            if (update)
                Console.Write("\b");
            Console.Write(_twirl[progress % _twirl.Length]);
        }
    }
}

This is the code in its entirety, so you don't really even have to download the link. Just copy this if you like.

If you happen to write console utilities, I hope you find this useful.

History

  • 6th January, 2020 - Initial submission

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
United States United States
Just a shiny lil monster. Casts spells in C++. Mostly harmless.

Comments and Discussions

 
QuestionI love it! Pin
CoryLoriot28-Apr-22 11:31
CoryLoriot28-Apr-22 11:31 
AnswerRe: I love it! Pin
honey the codewitch28-Apr-22 12:20
mvahoney the codewitch28-Apr-22 12:20 
QuestionCasting Spells in C# Pin
David A. Gray11-Jun-20 12:43
David A. Gray11-Jun-20 12:43 
AnswerRe: Casting Spells in C# Pin
honey the codewitch11-Jun-20 15:25
mvahoney the codewitch11-Jun-20 15:25 
GeneralRe: Casting Spells in C# Pin
David A. Gray12-Jun-20 5:46
David A. Gray12-Jun-20 5:46 
GeneralRe: Casting Spells in C# Pin
honey the codewitch12-Jun-20 7:48
mvahoney the codewitch12-Jun-20 7:48 
GeneralRe: Casting Spells in C# Pin
David A. Gray12-Jun-20 9:44
David A. Gray12-Jun-20 9:44 
GeneralRe: Casting Spells in C# Pin
honey the codewitch12-Jun-20 10:43
mvahoney the codewitch12-Jun-20 10:43 
GeneralRe: Casting Spells in C# Pin
David A. Gray13-Jun-20 8:48
David A. Gray13-Jun-20 8:48 
The simplicity of your approach is the reason I gave your article 5 stars. It's not often that you see a Code Project article that doesn't need a supporting download.

I had a very specific use case in mind in which capturing STDERR is important. When a console program runs as part of a scheduled task in a different user context (such as the SYSTEM account), it must be able to save anything critical that gets written to STDERR. Progress messages are incidental, and usually meaningless in that context.

I've written hundreds of console-mode programs, in VBScript, Perl, Python, C, C++, C#, and even assembler. Though most run in visible console windows, I've had a fair number of them that were destined to run in hidden consoles, mostly belonging to the SYSTEM account.

Bear in mind, too, that my use case involved strings of text, which got very messy when they found their way into a redirected stream file.

With all that said, on the whole, I agree with you. Where our viewpoints may differ is that I may start with that dead-simple use case, but, more often than not, I find new uses that break it, and the simple implementation that met the original use case gives way to a very robust implementation that can handle just about anything that you throw at it. That robust implementation almost always becomes part of a write-and-forget-about-it DLL.

Progress logging is a case in which that happened, and I rewrote the routine shortly after the publication of that article, 5 years ago. It's now part of a library that I put into an open source project, GitHub - txwizard/ConsoleAppAids3: Helper Classes for Character Mode Programs that Target the Microsoft .NET Framework 3.5 and Above. Since then, that method is essentially unchanged, although I eventually devised a way to eliminate the native code dependency in another library upon which it relies to determine when a stream is redirected. The library that contains that function is available on its own as Nuget package NuGet Gallery | WizardWrx.ConsoleStreams 7.15.191.37663.

The dependency is in GetStandardHandleState(), a static method on Class StandardHandleInfo, which is available separately as a like-named NuGet package, one of 11 closely related libraries that comprise my GitHub - txwizard/WizardWrx_NET_API.

Though I quit actively programming this past August, I still maintain these libraries, and they are in daily use, as tools, in my new work. Some were distributed to clients who were actively using them up until late last year.

In closing, real programmers use butterflies and miracles.
David A. Gray
Delivering Solutions for the Ages, One Problem at a Time
Interpreting the Fundamental Principle of Tabular Reporting

GeneralRe: Casting Spells in C# Pin
honey the codewitch13-Jun-20 12:55
mvahoney the codewitch13-Jun-20 12:55 
GeneralRe: Casting Spells in C# Pin
David A. Gray17-Jun-20 5:46
David A. Gray17-Jun-20 5:46 
QuestionHah, I just used this finally Pin
Marc Clifton29-Jan-20 9:05
mvaMarc Clifton29-Jan-20 9:05 
AnswerRe: Hah, I just used this finally Pin
honey the codewitch29-Jan-20 9:26
mvahoney the codewitch29-Jan-20 9:26 
QuestionThank You So Much! Pin
Goal Man7-Jan-20 20:44
Goal Man7-Jan-20 20:44 
AnswerRe: Thank You So Much! Pin
honey the codewitch7-Jan-20 22:52
mvahoney the codewitch7-Jan-20 22:52 
QuestionSome comments: Pin
Epsilon P7-Jan-20 6:34
Epsilon P7-Jan-20 6:34 
AnswerRe: Some comments: Pin
honey the codewitch7-Jan-20 7:28
mvahoney the codewitch7-Jan-20 7:28 
GeneralRe: Some comments: Pin
Epsilon P7-Jan-20 8:49
Epsilon P7-Jan-20 8:49 
GeneralRe: Some comments: Pin
honey the codewitch7-Jan-20 9:07
mvahoney the codewitch7-Jan-20 9:07 
GeneralRe: Some comments: Pin
Sacha Barber8-Jan-20 11:44
Sacha Barber8-Jan-20 11:44 
GeneralRe: Some comments: Pin
honey the codewitch8-Jan-20 12:18
mvahoney the codewitch8-Jan-20 12:18 
AnswerRe: Some comments: Pin
grantb410-Jan-20 6:48
grantb410-Jan-20 6:48 
GeneralRe: Some comments: Pin
honey the codewitch10-Jan-20 10:33
mvahoney the codewitch10-Jan-20 10:33 
QuestionA little improvement Pin
W. Kleinschmit7-Jan-20 3:17
W. Kleinschmit7-Jan-20 3:17 
AnswerRe: A little improvement Pin
honey the codewitch7-Jan-20 3:20
mvahoney the codewitch7-Jan-20 3:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.