Difference between revisions of "Command line parameters and environment variables"

From Lazarus wiki
Jump to navigationJump to search
(Undo revision 124749 by Martin (talk))
m (Fixed syntax highlighting)
Line 2: Line 2:
  
 
== Overview ==
 
== Overview ==
 
 
  
 
When a program is started a user can give [[Command-line interface|command line]] parameters and setup environment [[Variable|variables]]. For example the [[FPC|FreePascal]] [[Compiler|compiler]] gets most of its parameters via command line options:  
 
When a program is started a user can give [[Command-line interface|command line]] parameters and setup environment [[Variable|variables]]. For example the [[FPC|FreePascal]] [[Compiler|compiler]] gets most of its parameters via command line options:  
Line 17: Line 15:
 
A pascal program can access the parameters via ''ParamStr'' and ''ParamCount''. ''ParamStr(0)'' is the program name itself (and path _IF_ the operating system supports it) . ''ParamStr(1)'' is the first parameter. ''ParamCount'' is the number of parameters.
 
A pascal program can access the parameters via ''ParamStr'' and ''ParamCount''. ''ParamStr(0)'' is the program name itself (and path _IF_ the operating system supports it) . ''ParamStr(1)'' is the first parameter. ''ParamCount'' is the number of parameters.
  
<syntaxhighlight>program Project1;
+
<syntaxhighlight lang="pascal">
 +
program Project1;
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 27: Line 26:
 
   for I := 1 to ParamCount do
 
   for I := 1 to ParamCount do
 
     WriteLn('Param ', I, ': ', ParamStr(I));
 
     WriteLn('Param ', I, ': ', ParamStr(I));
end.</syntaxhighlight>
+
end.
 +
</syntaxhighlight>
  
 
For example:
 
For example:
Line 47: Line 47:
 
With TCustomApplication you can access parameters by name. For example your program should print a help text when the user gave the common help parameter ''-h''. The ''-h'' is a short option. The long form is the ''--help''. To test whether the user called the program with ''-h'' or ''--help'' you can use
 
With TCustomApplication you can access parameters by name. For example your program should print a help text when the user gave the common help parameter ''-h''. The ''-h'' is a short option. The long form is the ''--help''. To test whether the user called the program with ''-h'' or ''--help'' you can use
  
<syntaxhighlight>if HasOption('h', 'help') then begin
+
<syntaxhighlight lang="pascal">
 +
if HasOption('h', 'help') then begin
 
   WriteHelp;
 
   WriteHelp;
 
   Halt;
 
   Halt;
end;</syntaxhighlight>
+
end;
 +
</syntaxhighlight>
  
 
Note: In an LCL form you must prepend ''Application.'' in front of HasOption. For example:
 
Note: In an LCL form you must prepend ''Application.'' in front of HasOption. For example:
  
<syntaxhighlight>if Application.HasOption('h', 'help') then begin
+
<syntaxhighlight lang="pascal">
 +
if Application.HasOption('h', 'help') then begin
 
   WriteHelp;
 
   WriteHelp;
 
   Halt;
 
   Halt;
end;</syntaxhighlight>
+
end;
 +
</syntaxhighlight>
  
  
<syntaxhighlight>// If you only want to support the short option use:
+
<syntaxhighlight lang="pascal">
 +
// If you only want to support the short option use:
 
if HasOption('h', '') then ...
 
if HasOption('h', '') then ...
  
 
// If you only want to support the long option use:
 
// If you only want to support the long option use:
if HasOption('help') then ...</syntaxhighlight>
+
if HasOption('help') then ...
 +
</syntaxhighlight>
  
 
==== Read the parameter value ====
 
==== Read the parameter value ====
Line 76: Line 82:
 
   project1 --file=filename
 
   project1 --file=filename
  
<syntaxhighlight>WriteLn('f=', GetOptionValue('f', 'file'));</syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 +
WriteLn('f=', GetOptionValue('f', 'file'));
 +
</syntaxhighlight>
  
 
Note: if you get the error message ''Option at position 1 needs an argument : f.'' then you forgot to add the option in the ''CheckOptions'' call.
 
Note: if you get the error message ''Option at position 1 needs an argument : f.'' then you forgot to add the option in the ''CheckOptions'' call.
Line 87: Line 95:
  
 
Examples:
 
Examples:
<syntaxhighlight>ErrorMsg := CheckOptions('hf:', 'help file:');</syntaxhighlight>
+
<syntaxhighlight lang="pascal">
 +
ErrorMsg := CheckOptions('hf:', 'help file:');
 +
</syntaxhighlight>
  
 
This allows passing short options ''-f value'' and ''-h''. It allows passing long options ''--help'' or ''--file=filename''. It does not allow ''--help'' with a value, nor ''--file'' without a value.
 
This allows passing short options ''-f value'' and ''-h''. It allows passing long options ''--help'' or ''--file=filename''. It does not allow ''--help'' with a value, nor ''--file'' without a value.
Line 93: Line 103:
 
'''A Parameter Example :'''
 
'''A Parameter Example :'''
  
<syntaxhighlight>procedure TMainForm.FormShow(Sender: TObject);
+
<syntaxhighlight lang="pascal">procedure TMainForm.FormShow(Sender: TObject);
 
var
 
var
 
     I: Integer;
 
     I: Integer;
Line 107: Line 117:
 
         FreeAndNil(Params);
 
         FreeAndNil(Params);
 
     end;
 
     end;
end;</syntaxhighlight>
+
end;
 +
</syntaxhighlight>
 +
 
 
This example finds parameters and does not mix them with command line switches or options. In this example, the app also accepts the switches --debug-sync and --config-dir=somedir but they are not reported here.
 
This example finds parameters and does not mix them with command line switches or options. In this example, the app also accepts the switches --debug-sync and --config-dir=somedir but they are not reported here.
  
Line 125: Line 137:
 
Example:  
 
Example:  
  
<syntaxhighlight>var
+
<syntaxhighlight lang="pascal">
 +
var
 
   I: Integer;
 
   I: Integer;
 
begin
 
begin
Line 133: Line 146:
 
   for I := 0 to GetEnvironmentVariableCount - 1 do  
 
   for I := 0 to GetEnvironmentVariableCount - 1 do  
 
     WriteLn(GetEnvironmentString(I));
 
     WriteLn(GetEnvironmentString(I));
end.</syntaxhighlight>
+
end.
 +
</syntaxhighlight>
  
 
It is also possible to load all environment variables to TStringList object and access to name-value pair easily. String list automatically handle char separator which is by default character '='.
 
It is also possible to load all environment variables to TStringList object and access to name-value pair easily. String list automatically handle char separator which is by default character '='.
  
<syntaxhighlight>var
+
<syntaxhighlight lang="pascal">
 +
var
 
   I: Integer;
 
   I: Integer;
 
   EnvVars: TStringList;
 
   EnvVars: TStringList;
Line 155: Line 170:
 
     EnvVars.Free;
 
     EnvVars.Free;
 
   end;
 
   end;
end.</syntaxhighlight>
+
end.
 +
</syntaxhighlight>
  
 
There is also TApplication method available to get all environment variables as TStrings list at once.
 
There is also TApplication method available to get all environment variables as TStrings list at once.
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
var
 
var
 
   EnvVars: TStringList;
 
   EnvVars: TStringList;

Revision as of 06:13, 8 February 2020

English (en) español (es) suomi (fi) français (fr) русский (ru)

Overview

When a program is started a user can give command line parameters and setup environment variables. For example the FreePascal compiler gets most of its parameters via command line options:

 fpc -Fudirectory -gh unit1.pas

In this example the "-Fudirectory -gh" are command line switches and the "unit1.pas" is a parameter.

Command line parameters

The basics

A pascal program can access the parameters via ParamStr and ParamCount. ParamStr(0) is the program name itself (and path _IF_ the operating system supports it) . ParamStr(1) is the first parameter. ParamCount is the number of parameters.

program Project1;

{$mode objfpc}{$H+}

var
  I: Integer;
begin
  WriteLn('Program: ', ParamStr(0));
  for I := 1 to ParamCount do
    WriteLn('Param ', I, ': ', ParamStr(I));
end.

For example:

 $ /tmp/project1 -a
 Program: /tmp/project1
 Param 1: -a

User friendly

A good program should give a help message when invoked with the wrong parameters and it should follow a common way of giving parameters. The unit custapp that comes with FPC provides the TCustomApplication class, which provides functions to easily check and read parameters. Of course you can still access the parameters directly via ParamStr and ParamCount.

Every LCL application uses this automatically. The Application object is a TCustomApplication.

If you want to write a non LCL program, then create in lazarus a new project of type 'Console Application'. This will create a project1.lpr with some nice goodies, that almost all programs need. Go to the DoRun method.

Check for a parameter

With TCustomApplication you can access parameters by name. For example your program should print a help text when the user gave the common help parameter -h. The -h is a short option. The long form is the --help. To test whether the user called the program with -h or --help you can use

if HasOption('h', 'help') then begin
  WriteHelp;
  Halt;
end;

Note: In an LCL form you must prepend Application. in front of HasOption. For example:

if Application.HasOption('h', 'help') then begin
  WriteHelp;
  Halt;
end;


// If you only want to support the short option use:
if HasOption('h', '') then ...

// If you only want to support the long option use:
if HasOption('help') then ...

Read the parameter value

Each parameter can be given a value. For example:

 project1 -f filename

or with the long form:

 project1 --file=filename
WriteLn('f=', GetOptionValue('f', 'file'));

Note: if you get the error message Option at position 1 needs an argument : f. then you forgot to add the option in the CheckOptions call.

Checking parameters for validity

Command line parameters are free text, so the user can easily type errors. Checking the syntax of the parameters is therefore mandatory. You can use the CheckOptions method for this:

You can define, what parameters are allowed, which ones ones need a parameter and in case of a syntax error you can get an error message plus the options that were wrong to print helpful and detailed errors.

Examples:

ErrorMsg := CheckOptions('hf:', 'help file:');

This allows passing short options -f value and -h. It allows passing long options --help or --file=filename. It does not allow --help with a value, nor --file without a value.

A Parameter Example :

procedure TMainForm.FormShow(Sender: TObject);
var
    I: Integer;
    Params : TStringList
    LongOpts : array [1..2] of string = ('debug-sync', 'config-dir:');
begin
    Params := TStringList.Create;
    try
        Application.GetNonOptions('hgo:', LongOpts, Params);
        for I := 0 to Params.Count -1 do
            debugln('Extra Param ' + inttostr(I) + ' is ' + Params[I]);  }
    finally
        FreeAndNil(Params);
    end;
end;

This example finds parameters and does not mix them with command line switches or options. In this example, the app also accepts the switches --debug-sync and --config-dir=somedir but they are not reported here.

Note that Application.GetNonOptions() takes the long options as an array but Application.CheckOptions takes the same data but as a string. Bit sad !

Environment variables

Three basic functions are provided for working with environment variables.

GetEnvironmentVariable

GetEnvironmentString

GetEnvironmentVariableCount


Example:

var
  I: Integer;
begin
  WriteLn('PATH = ' + GetEnvironmentVariable('PATH'));

  WriteLn('All environment variables:');
  for I := 0 to GetEnvironmentVariableCount - 1 do 
    WriteLn(GetEnvironmentString(I));
end.

It is also possible to load all environment variables to TStringList object and access to name-value pair easily. String list automatically handle char separator which is by default character '='.

var
  I: Integer;
  EnvVars: TStringList;
begin
  EnvVars := TStringList.Create;
  try
    // Load all variables to string list
    for I := 0 to GetEnvironmentVariableCount - 1 do 
      EnvVars.Add(GetEnvironmentString(I));

    WriteLn('PATH = ' + EnvVars.Values['PATH']);

    WriteLn('All environment variables:');
    for I := 0 to EnvVars.Count - 1 do 
      WriteLn(EnvVars.Names[I] + ' = ' + EnvVars.ValueFromIndex[I]);
  finally 
    EnvVars.Free;
  end;
end.

There is also TApplication method available to get all environment variables as TStrings list at once.

var
  EnvVars: TStringList;
begin
  EnvVars := TStringList.Create;
  try
    Application.GetEnvironmentList(EnvVars);
    ...
  finally 
    EnvVars.Free;
  end;
end;