The article introduces Command Line GUI, a shared library inspired by the Plossum library, which allows rapid development of console apps with parameters and options, providing a GUI without additional programming. It demonstrates how to develop plugins for existing command line programs or console apps utilizing Plossum, using a data model class and attributes to describe options, and how Command Line GUI can handle multiple plugins.
Introduction
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, especially if you have different combinations of more than 5 parameters. I had used the Plossum library by Peter Palotas in a few projects for parsing command line options. And this library had inspired to develop Command Line GUI.
This article introduces:
- How to rapidly develop a console app with a few parameters and many options. Fonlow.CommandLineGui.Core.dll is compatible with the
Plossum
Library, with additional features. - The console app could have a GUI without the need for further programming.
- For an existing command line program on any platform, you can even give it a GUI.
Remarks
The source codes of Command Line GUI contain some fragments of the Plossum
library, in Core/PlossumFragment, for giving you the same API of declarative programming. If you had been using the Plossum
library, you could easily migrate to Command Line GUI and remove the dependency on the Plossum
library.

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 to the next one.
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);
Console.WriteLine(parser.ApplicationDescription);
parser.Parse();
Console.WriteLine(options.DurationInSecond);
if (options.Help)
{
Console.WriteLine(parser.UsageInfo.GetOptionsAsString(78));
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 = "Demonstrate 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=http://csharpoptparse.sourceforge.net/", 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
{
get;
set;
}
[CommandLineOption(Aliases = "OE",
Description = "enum text", GroupId = "detail")]
public MyEnum OkEnum
{
get;
set;
}
}
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.
[MyPlosum.jpeg]
Command Line GUI
You may be asking why we need a GUI for an existing command line program.
Background
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. And there is actually Robocopy GUI from Microsoft, and there are quite a few other similar programs if you search the Internet, however, none of them satisfied me. So I had developed Better Robocopy GUI in 2009.
Generally, IT admins 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 (dead link in codeplex.com).
Sometime, you might have developed a command line program called DoWonderfulThings
, and the IT admins or 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 person 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 DoWonderfulThings
GUI anyway. Next time you will develop DoBetterThings
, and then DoBetterThings
GUI, and so on. If you don’t mind repeating such development process, and carry out such jobs again and again, you may not be interested in what is described below.
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, then I hand 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 existing 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";
[Category(COPY_OPTIONS)]
[Description("Copies subdirectories (excluding empty ones).")]
[DisplayName("/S")]
[DefaultValue(false)]
public bool SlashS
{
get;set;
}
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;
[Category(COPY_OPTIONS)]
[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 information." + "\n\r" +
"Source and destination volumes must both be NTFS to copy Security,
Ownership or Auditing information.")]
[DisplayName("/COPY:")]
[DefaultValue(CopyFlags.None)]
[NameValueNoSpace]
[Editor(typeof(CopyFlagsEditor), typeof(UITypeEditor))]
public CopyFlags SlashCopy
{
get;set;
}
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 is described by those BCL attributes overlap with what is 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
{
get;
set;
}
[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.
Prerequisites
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 Existing 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 a parameters data model class describing each fixed parameter or option through a property; decorate each property presenting 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 are 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
{
get;
set;
}
[CommandLineOption(Name = "E", GroupId = OptionGroups.COPY_OPTIONS,
Description = "Copies all subdirectories (including empty ones).")]
public bool SlashE
{
get;
set;
}
Hints
- 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. - 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 Console App that Utilizes Plossum
You had developed a .NET console app DoWonderfulThings.exe 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 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 changed, you may go to https://sourceforge.net/p/commandlinegui/code/91/tree/branches/Plossum/ and compare with https://sourceforge.net/p/plossum/code/25/tree/trunk/.
In addition to the 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 for giving you the same API of declarative programming. So you need Plossum.dll no more but Antlr4.Runtime.v4.0.dll. The API in Fonlow.CommandLineGui.Core.dll is compatible with Plossum
Library, and additionally supports fixed parameters, array, and options rules of exclusion, inclusion and combination.
Configuration
The configuration is stored in CommandLineGui.exe.config.
<applicationSettings>
<Fonlow.CommandLineGui.Settings>
<setting name="PluginAllocationMethod" serializeAs="String">
<value>Registration</value>
</setting>
<setting name="AssemblyNames" serializeAs="Xml">
<value>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>RobocopyParameters</string>
<string>MyPlossum</string>
</ArrayOfString>
</value>
</setting>
</Fonlow.CommandLineGui.Settings>
</applicationSettings>
<userSettings>
<Fonlow.CommandLineGui.Settings>
<setting name="AssemblyNameOfCommand" serializeAs="String">
<value>RobocopyParameters</value>
</setting>
</Fonlow.CommandLineGui.Settings>
</userSettings>
Mono
You may set Command Line GUI to run with only one program through assigning PluginAllocationMethod
with value Mono.
Registration
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.
Summary
Command Line GUI project includes a library compatible with Plossum so you can use declarative programming to define options and skip writing a parser. This library supports 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.
So you will get the best of both worlds: command line and GUI.
Points of Interests
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:
- Support strong typing options.
- Support rules of inclusion, exclusion and combination.
- Introduce least foot print in your application codes while giving professional looks.
- Have comprehensive test suits to ensure the correctness in common formats of Windows command line programs.
References

History
- 9th September, 2013: Initial version
- 29th July, 2023: Update