Click here to Skip to main content
11,930,069 members (37,804 online)
Click here to Skip to main content
Add your own
alternative version


54 bookmarked

Get the Best of Both Worlds: Command Line and GUI

, 16 May 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Rapidly develop a console with a lot options and give a command line program a GUI

You might have developed some command line programs (console apps in .NET) which might be utilities or business applications of batch processing etc. Often the console app takes a few parameters and options, and you need to write codes to parse the arguments. I believe many of us might have written some ad-hoc parsers for such purpose. It is better to have a shared library to take care of the parsing job. I had used Plossum library by Peter Palotas in a few projects for parsing command line options. This article introduces how to rapidly develop a console app with a few parameters and many options, and the console app could have a GUI without the need for further programming. And you can even give an existing command line program not in .NET a GUI.

Command Line Options with Plossum

If you have read the “Powerful and simple command line parsing in C#” and used Plossum in your console apps, you may skip this chapter and go next.

This demo program below gives you a snapshot of using Plossum in a console app through declarative programming.

using System;
using Plossum.CommandLine;
using Fonlow.CommandLine;

namespace MyPlossum
    class Program
        static int Main(string[] args)
            var options = new Options();
            CommandLineParser parser = new CommandLineParser(options);
            if (options.Help)
                return 0;
            if (parser.HasErrors)
                Console.WriteLine(parser.UsageInfo.ToString(78, true));
                return 1;
            Console.WriteLine(String.Format("{0} is executed.", parser.ApplicationName));
            return 0;
    [CommandLineManager(ApplicationName = "MyPlossum", Description = "Demostrate the power of Plossum", EnabledOptionStyles = OptionStyles.Windows, Copyright="Fonlow (c) 2013", Version="1.1")]
    [CommandLineOptionGroup("detail", Name = "Detail")]
    [CommandLineOptionGroup("other", Name = "Other")]
    public class Options
        [CommandLineOption(Aliases = "F", Description = "Function name, e.g., /F=FirstFunction")]
        public string Function { get; set; }
        [CommandLineOption(Description = "URL. e.g., /Url=",  GroupId = "detail")]
        public string Url { get; set; }
        [CommandLineOption(Aliases = "du", Name = "Duration", Description = "Duration in second.", RequireExplicitAssignment = true, DefaultAssignmentValue = 3600.08d, GroupId = "detail")]
        public double DurationInSecond { get; set; }
        [CommandLineOption(Aliases = "h", Description = "Shows this help text", GroupId = "other")]
        public bool Help
        [CommandLineOption(Aliases = "OE", Description = "enum text", GroupId = "detail")]
        public MyEnum OkEnum
    public enum MyEnum { None, Hello, World, Plossum };

So you need to define a data object class “Options” describing the options as data model, and decorate the properties with CommandLineOptionAttribute, and the command line parser of Plossum library will do the heavy lifting of parsing arguments into the Options object. And your console could have a professional look with online help.

Command Line GUI

You may be asking why we need a GUI for an existing command line program.


Back to many years ago I had found Robocopy.exe for synchronizing files between 2 drives. This command line program is very powerful with a few dozens options, and comes with even a manual robocopy.doc in addition to the online help. It is apparently not convenient for many people including me to remember the options or look up the manual, so that there is actually Robocopy GUI from Microsoft as well, and there are quite a few others similar programs if you search the Internet, however, none of them satisfied me. So I had developed Better Robocopy GUI in 2009.

Generally, system guys like Robocopy, and casual users and non-technical people like Robocopy GUI. I am a software developer and a casual user of Robocopy, so I need a Better Robocopy GUI.

Sometime, you might have developed a command line program called DoWonderfulThings, and the support guys use it for daily operations; then Alice from the Marketing Department would like to DoWonderfulThings as well, however, she is apparently not the kind of people who would appreciate remembering and typing command line options. So you are going to write DoWonderfulThings GUI as Derk Benisch in Microsoft had done for Robocopy. You get paid to develop anyway. Next time you will develop DoBetterThings, and then DoBetterThings GUI, and so on. If you don’t mind repeating such development process, and carryout such jobs again and again, you may not be interested in what described following.

Soon after releasing Better Robocopy GUI, I found that it was fairly easy to refactor the program’s structure to make it support other command line programs of which people may desire to have GUI, so I created a fork of Better Robocopy GUI called Command Line GUI. And Robocopy related functionality becomes the primary plug-in of Command Line GUI, while you will be able to develop plugin for other command line programs.

A typical plugin needs to define a data model describing options as properties and decorate each property with some attributes understood by PropertyGrid which will render each property with proper GUI controls.

namespace Fonlow.CommandLineGui.Robocopy
    public class Options
        const string TOP_CATEGORY = " ";
        const string COPY_OPTIONS = "Copy Options";
        const string LOGGING_OPTIONS = "Logging Options";
        const string RETRY_OPTIONS = "Retry Options";
        const string FILE_SELECTION_OPTIONS = "File Selection Options";

        [Description("Copies subdirectories (excluding empty ones).")]
        public bool SlashS

        const CopyFlags fullCopy = CopyFlags.A | CopyFlags.D | CopyFlags.O | CopyFlags.S | CopyFlags.T | CopyFlags.U;
        const CopyFlags secCopy = CopyFlags.D | CopyFlags.A | CopyFlags.T | CopyFlags.S;

        [Description("Copies the file information specified by copyflags, which can be any combination of the following :" + "\n\r" +
"D – file Data. S – file Security (NTFS ACLs)." + "\n\r" +
"A – file Attributes. O – file Ownership information." + "\n\r" +
"T – file Timestamps. U – file aUditing infomation." + "\n\r" +
"Source and destination volumes must both be NTFS to copy Security, Ownership or Auditing information.")]
        [Editor(typeof(CopyFlagsEditor), typeof(UITypeEditor))]
        public CopyFlags SlashCopy

Basically, DisplayNameAttribute gives the option name, DescriptionAttribute defines content to be displayed in the hint area of the PropertyGrid, and DefaultValueAttribute will let PropertyGrid know whether to render a modified option value in Bold, while CategoryAttribute groups options, and EditorAttribute introduces a custom editor for a type of option, such as flagged enumeration.

This is how Command Line GUI v1.x works. And v2.0 had undergone major structure changes and face-lift, so that giving a command line program a GUI has become even easier.

Command Line GUI with Plossum

As you have seen so far, Command Line GUI and Plossum share the same design concept of using a data model class as well as attributes to describe options. It sounds natural that a console application utilizing Plossum may easily get into Command Line GUI through further decoration with DisplayNameAttribute, DefaultValueAttribute and EditorAttribute etc. However, obviously what described by those BCL attributes overlap what described by named properties of Plossum’s CommandLineOptionAttribute.

BCL attributes Named properties of CommandLineOptionAttribute
DisplayName Name or Alias
Description Description
DefaultValue DefaultAssignmentValue
Category GroupId

PropertyGrid requires those BCL attributes to render GUI controls, while Plossum needs CommandLineOptionAttribute to parse command line options. And having redundant descriptions of those properties of the Options data model class does not look nice and productive, though working.

To make life easier, in Command Line GUI v2.0 and v3.0, the development work of a plugin will need CommandLineOptionAttribute only, so you may define the properties of Option this way:

        [CommandLineOption(Name = "A-", GroupId = OptionGroups.COPY_OPTIONS, 
            Description = "Turns off the specified attributes in copied files.\n\rThe following attributes can be turned off:\n\r" +
"R – Read only S – System N – Not content indexed\n\rA – Archive H – Hidden T – Temporary")]
        [Editor(typeof(RashFlagsEditor), typeof(UITypeEditor))]
        public Rashcneto SlashAMinus

        [CommandLineOption(Name = "CREATE", GroupId = OptionGroups.COPY_OPTIONS, 
            Description = "Creates a directory tree structure containing zero-length files only (that is, no file data is copied).")]
        public bool SlashCreate { get; set; }

Then Command Line GUI will generate PropertyGrid consumable BCL attributes for the options type at run time dynamically.


To develop a console app utilizing Plossum or write a plugin for Command Line GUI, you need to download Command Line GUI binaries or its source codes.

File Name Description
Fonlow.CommandLineGui.Core.dll Core library, for command line programs.
Fonlow.CommandLineGui.Gui.dll GUI components.
Antlr4.Runtime.v4.0.dll Antlr .NET
RobocopyParameters.dll Robocopy plugin.
CommandLineGui.exe Main executable

You may checkout the source codes and particularly check project MyPlossum and project RobocopyParameters in the Examples solution folder.

Develop Plugin for Windows native command line application

Using Robocopy as example, you may follow these steps:

Step 1: Create a class library for Robocopy.

Step 2: Add project reference to Fonlow.CommandLineGui.Core.dll, and optionally Fonlow.CommandLineGui.Gui.dll if you need some custom editors for some options.

Step 3: Write an parameters data model class describing each fixed parameter or option through a property; decorate each property presentinging a fixed parameter with FixedParameterAttribute; decorate each property representing an option with CommandLineOptionAttribute; and optionally decorate with an EditorAttribute for introducing a custom editor.

Step 4: Register the assembly of the class library in CommandLineGui.exe.config. And copy RobocopyParameters.dll to the program directory of Command Line GUI.

The following codes is for Robocopy.

[CommandLineManager(ApplicationName = "Robocopy", Description = "Robocopy options", RequireExplicitAssignment = true)]
public class RobocopyOptions
    [FixedParameter(Category = OptionGroups.TOP_CATEGORY, Description = @"Source Directory (drive:\path or \\server\share\path).",
        DisplayName = "Source", Order = 1, DefaultValue = "SourceDir")]
    public string Source { get; set; }

    [FixedParameter(Category = OptionGroups.TOP_CATEGORY, Description = @"Destination Dir  (drive:\path or \\server\share\path).",
       DisplayName = "Destination", Order = 2, DefaultValue = "DestDir")]
    public string Destination { get; set; }

    [FixedParameter(Category = OptionGroups.TOP_CATEGORY, Description = "File(s) to copy  (names/wildcards: default is \"*.*\").",
     DisplayName = "Files", Order = 3, DefaultValue = "FilesSeparatedBySpace")]
    public string[] Files { get; set; }

    [CommandLineOption(Name = "?",
        Description = "Usage info and help.")]
    public bool Help
    { get; set; }

    [CommandLineOption(Name = "S", GroupId = OptionGroups.COPY_OPTIONS,
        Description = "Copies subdirectories (excluding empty ones).")]
    public bool SlashS

    [CommandLineOption(Name = "E", GroupId = OptionGroups.COPY_OPTIONS,
        Description = "Copies all subdirectories (including empty ones).")]
    public bool SlashE


  1. Command Line GUI will instantiate the first class decorated by CommandLineManagerAttribute in the assembly, so please make sure you define only one such class in the assembly.
  2. If you want to define rules of inclusion, exclusion and combination among options, you may check the source codes of the Robocopy plugin for some clues.

Develop Plugin for a .NET console app that utilizes Plossum

You had developed a .NET console app DoWonderfulThings that utilizes Plossum, now your customers want a GUI.

Step 1: Add project reference to Fonlow.CommandLineGui.Core.dll, and optionally Fonlow.CommandLineGui.Gui.dll if you need some custom editors for some options; and remove reference to Plossum.dll.

Step 2: Register DoWonderfulThings in CommandLineGUI.exe.config. And copy DoWonderfulThings.exe to the program directory of Command Line GUI.

In short, you just need to rebuild the assembly with new references, then you get GUI.

You need only Plossum attributes without referencing to Plossum.dll

During the development of Command Line GUI v2.0, I had found a few minor defects in Plossum 0.4 which prevent Command Line GUI from using it. For console applications, Plossum 0.4 had actually served its original purpose perfectly. Now Plossum is running in a Winforms program, and the codes could not deal with such new environment, so I had to create a fork from Plossum 0.4 and fixed those minor defects. If you are interested in what I had change, you may go to and compare with

In addition to the those minor fixes, in Command Line GUI v2.0, I had removed Plossum’s dependency on C5.dll. Peter had made it clear in 2007 that he had chosen C5.dll because it was powerful and easy to use comparing with .NET Framework 2. However, Command Line GUI v2.0 targets .NET Framework 4, so the advantage C5.dll has been fading in this landscape. Therefore you should be using Plossum v0.5 which is compatible with v0.4 at API level while having NO dependency on C5.dll.

In Command Line GUI v3.0, I had rewritten the command line arguments parser on top of ANTLR, and only a small fragment of Plossum codes is kept. So you need no Plossum.dll any more but Antlr4.Runtime.v4.0.dll. The API in Fonlow.CommandLineGui.Core.dll is compatible with Plossum Library, and additiohnally supports fixed parameters, array, and options rules of exclusion, inclusion and combination.


The configuration is stored in CommandLineGui.exe.config.

    <setting name="PluginAllocationMethod" serializeAs="String">
      <!-- Registration for handling multiple command line programs
      or Mono for only 1 program listed in the first item of AsssemblyNames.-->
    <setting name="AssemblyNames" serializeAs="Xml">
      <!--Each assembly name should not contain file extension name such as dll or exe.-->
        <ArrayOfString xmlns:xsi=""

    <!--This setting is effective only if PluginAllocationMethod is Registration. And the actual value is in AppData of the user profile area.-->
    <setting name="AssemblyNameOfCommand" serializeAs="String">


You may set Command Line GUI to run with only one program through assigning PluginAllocationMethod with value Mono.


If you want one instance of Command Line GUI to handle multiple plugins, you may assign PluginAllocationMethod with value Registration. In addition, you need to copy respective assemblies to the program directory of Command Line GUI and register each in setting AssemblyNames each of which should NOT contain file extension name such as dll or exe.


Command Line GUI conisists of a library similar to Command Line Parser Library and Plossum so you can use declarative programming to define options and skip writting a parser. This library supprt more complex combinations of options, as seen in Robocopy.

Command Line GUI renders GUI controls for command line programs which are built on the API in Fonlow.CommandLineGui.Core.dll. The API is compatible with Plossum Library, and supports fixed parameters, array, and rules.

So you will get the best of both worlds: command line and GUI.

Points of Interests

If you have been using the Plossum library for years, you might be interested in new features and breaking changes in addition to orignal Plossum's features. Please check the Wiki pages.

If you google "C# command line arguments parser", you will find a long list of codes or libraries for parsing command line arguments. You may check if they:

  1. Support strong typing options.
  2. Support rules of inclusion, exclusion and combination.
  3. Introduce least foot print in your application codes while giving professional looks.
  4. Have comprehensive test suits to ensure the correctness in common formats of Windows command line programs.




This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer
Australia Australia
I started my IT career in programming on different embedded devices since 1992, such as credit card readers, smart card readers and Palm Pilot. Programming on the hardware was really fun, feeling like driving the hardware directly.

Beside technical works, I enjoy reading literatures, playing balls, cooking and gardening.

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Volynsky Alex18-May-14 5:59
professionalVolynsky Alex18-May-14 5:59 
QuestionI like it Pin
hillstream9-Feb-14 16:56
memberhillstream9-Feb-14 16:56 
AnswerRe: I like it Pin
Zijian9-Feb-14 18:06
memberZijian9-Feb-14 18:06 
GeneralRe: I like it Pin
hillstream9-Feb-14 21:57
memberhillstream9-Feb-14 21:57 
GeneralRe: I like it Pin
hillstream9-Feb-14 22:22
memberhillstream9-Feb-14 22:22 
GeneralMy vote of 5 Pin
BrunoHewitt16-Sep-13 2:05
memberBrunoHewitt16-Sep-13 2:05 
GeneralMy vote of 5 Pin
fredatcodeproject9-Sep-13 1:05
memberfredatcodeproject9-Sep-13 1:05 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151126.1 | Last Updated 16 May 2014
Article Copyright 2013 by Zijian
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid