Suggestions for how to define command line parameters

5.1k Views Asked by At

In my Delphi application, I would like to add command line parameters to automatically set some parameters in the login screen.

Currently I have a login screen where the user sets some information (like Server, database, user, password, AuthenticationType, AUtoLogin, ...).

I use MRU to populate the fields. Anyway, in big organizations, there is the need to do not let the user choose any info. For this, the simplest thing I can do in my scenario is to use command line parameters.

My question is how do you suggest to choose the command line parameters? I mean, should I go for a "position" approach or for some "tag" approach, for example:

MyProject.exe -s:MYSERVER -d:DATABASE

or

MyProject.exe MYSERVER DATABASE

In the first case I need to loop across all parameters using ParamStr and "decode" what they are. If they start with "-s:" I know that what follows is the server name. The second is more quick and dirty but may be more effective.

How to manage parameters that contain a "space"? Is it possible to automatically intercept them with ParamStr or should I handle all manually? (I mean is there a way to automatically tell to ParamStr that a parameter is containing a space (like using curly brackets or something).

What is the best practice?

4

There are 4 best solutions below

4
David Heffernan On BEST ANSWER

Should I go for a "position" approach or for some "tag" approach?

Without doubt you should tag your command line arguments. Positional approaches don't allow sufficient flexibility to omit parameters. Tagging makes it easier for the user to understand the arguments, especially when returning to previously written code. The tags should be self-documenting.

One common scenario when you would have untagged arguments is when you have a file name or a list of file names.

How to manage parameters that contain a "space"?

The Windows convention is that spaces are escaped by putting double-quotes around the argument. The ParamStr parsing will recognise these and parse the arguments accordingly. What you see in ParamStr(i) is the argument with the quotes removed.


The RTL comes with a useful helper function to aid your command-line argument parsing: FindCmdLineSwitch.

1
Andreas Rejbrand On

Your first question is merely a matter of taste. However, the second one I can answer. You use double quotation marks to enclose a parameter containing spaces. For example, if you have

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  i: integer;

begin
  for i := 0 to ParamCount do
    WriteLn(ParamStr(i));
  Readln;
end.

and start the application with arguments one "two with spaces" three "four with spaces", then you get the output

C:\Users\Andreas Rejbrand\Documents\RAD Studio\Projects\Project1.exe
one
two with spaces
three
four with spaces
0
Lars Fosdal On

I'd separate Arguments (order based) and Options (switch based) See "c:>help copy" for example.

2
Jeroen Wiert Pluimers On

Delphi contains a really nice unit called CommandParser with a TCommandParser class that does commandline parsing for you.
Since it has virtually no documentation, here are a few things to get started.

I have a HiddenExecutable example at our open source bo repository.

Basically you:

  • setup a TComponent that contains the properties you want to expose as commandline parameters (that is THiddenExecuteSettings in the HiddenExecuteSettingsUnit
  • a commandline parser controller. In our case THiddenExecuteArguments in the THiddenExecuteArgumentsUnit (in retrospect not such a good name) that contains an InitCommandLine method that sets up a TCommandParser instance passing it your TComponent
  • It then executes a couple of AddSwitch calls to setup the parameters with both abbreviated and full commandline switches (like h and help)
  • You can then call the ProcessCommandLine method on the TCommandParser instance to process the commandline and fill the properties of your TComponent (in my example, this is done in the ProcessCommandLine method).

Now comes the fun:

  • The TCommandParser has a HelpText method that fully automatically assembles a helptext based upon what you fed it with the AddSwitch methods.
  • The TCommandParser also has a SaveOptions method that allows you to save the current settings of your TComponent into a settings file.

The Delphi units you need are these which you can get from the Embarcadero radstudiodemos.sourceforge.net demo repository:

CommandParser in '...\radstudiodemos.sourceforge.net\branches\RadStudio_XE2\Delphi\Database\dbExpress\Utils\CommandParser.pas',
PropertyHelpers in '...\radstudiodemos.sourceforge.net\branches\RadStudio_XE2\Delphi\Database\dbExpress\DbxDataPump\PropertyHelpers.pas',
ParseIds in '...\radstudiodemos.sourceforge.net\branches\RadStudio_XE2\Delphi\Database\dbExpress\DbxDataPump\ParseIds.pas',

Edit: John Kaster wrote a nice article on EDN that includes more details on using the TCommandParser.