Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#1

Programmparameter auslesen

  Alt 31. Mai 2010, 14:38
Einige kennen das bestimmt, wie schwer sich manchmal die Parameter auswerten lassen,
vorallem wenn die Parameter keine feste Reihenfolge besitzen und wenn man sie mit Namen ansprechen möchte.

Über ParamStr und ParamCount hat man ja leider nicht viele Möglichkeiten zur Behandlung der Parameter.
  • Diese Klasse zerlegt nun also die Programmparameter oder irgendeinen anderen Parameterblock.
  • Man kann Parameter direkt über einen Namen ansprechen und muß nicht erst alle Parameter durchgehen.
  • Über CommandPrefix und ValueSeperator wird ein gewünschtes Format angegeben.
  • Mit den EOP-Varianten (to EndOfParameterblock) kann man auch auf ganze Bereiche zugreifen.
    Es werden in diesen Fällen alle Daten ab der gewünschten Stelle geliefert ... bis zum Ende des Parameterblocks.
    (gut für Fälle, in welchen z.B. aufgrund fehlender " Parameter nicht richtig ausgelesen werden können)
  • es werden verschiedene Syntax für den Named-Zugriff erkannt:
    (im Beispiel CommandPrefix = "-" und ValueSeperator = ":" )
    > -name
    > -name:value
    > -name:: value

    (bei doppeltem Seperator kann der Value als einzelner nachfolgender "Parameter" definiert sein)
  • In Bezug auf Leerzeichen kann man, wie gewohnt, mit dem " maskieren:
    > -"na me"
    > -"na me":"val ue"
    > -"na me:val ue"
    > -name:"val ue"
    > -name:: "val ue"
    > uvm.

    Achtung: > "-name... < wird nicht als Named-Parameter erkannt, sondern das "-" wird mit zum Value gezählt.
  • Man muß auch nicht jeden Parameter selber durchlaufen, sondern kann sich auch über einen Callback (siehe Parse-Prozedur) alles liefern lassen.
  • Achtung 2: Param[0] liefert nicht immer den gewohnten Pfad zur eigenen Anwendung,
    sondern dieses liefert den "String" über welchen die Anwendung gestartet wurde.
    wenn z.B. in einer Batch-Datei nur "MeineDatei.exe" steht, dann liefert Param[0] auch nur genau dieses.

    Alternativ kann man weiterhin ParamStr(0), Application.ExeFile oder hier enthaltene GetModule verwenden.
  • GetModulePath entspricht ExtractFilePath(Application.ExeFile)
  • die grundsätzlchen Prefixe und Seperatoren / - : und = werden nun standardmäßig alle erkannt,
    aber wenn man über Param zugreift, dann werden diese nach - und = konvertiert.
    (also jeweils zum ersten eingestellten Paar)
  • hat man also zwei Prefix-Seperator-Paare eingestellst, so werden Beide erkannt,
    aber auswerten braucht man dennoch nur das erste Paar


Anzuwenden ist es relativ einfach ... z.B. so
Delphi-Quellcode:
with TParameter.Create do
  try
    CommandPrefix := '/';
    ValueSeperator := '=';

    if Exists['file'] then // für /file:"c:\irgendwo\dat.ei"
      ShowMessage(Value['file']);
  finally
    Free;
  end;
Es gibt 3 Versionen:
  • Class 2009+ & ANSI 7-2007:
    Diese Version paßt sich ans Delphi an und arbeitet somit bis Delphi 2007 nur mit ANSI
    und ab Delphi 2009 mit Unicode.
  • Class 7-2007:
    Diese Version nutzt WideStrings, sowie eine eigene ExtractFilePath-Routine
    und ist vorgesehn um in älteren Delphis Unicode zur Verfügung zu stellen.
    (ab Delphi 2009 sollte aber besser die andere Class-Version verwendet werden)
  • Record 2009+:
    Dieses ist eine Record-Version des Ganzen und bietet somit die Vorteile einer entfallenden Initialisierung, sowie Finalisierung (keine Möglichkeit für Speicherlecks) und teilweise eine einfachere Verwendung (wird wie ein Interface freigegeben und initialisiert sich spätestens bei erster Verwendung automatisch)

    Sie dürfte auch ab Delphi 2006 / TurboDelphi mit ANSI laufen.

Selber nutze ich die Record-Variante ein, welche man so verwenden klnnte
Delphi-Quellcode:
with TParameter.GetDefault do begin
  if Exists['file'] then ShowMessage(Value['file']);
  ...
end;
Delphi-Quellcode:
var Params: TParameter;

if Params.Exists['file'] then ShowMessage(Params.Value['file']);
...
hier die wichtigsten Header der Record-Variante (die Classen-Varianten sehn ähnlich aus)
Delphi-Quellcode:
// possible parameter combinations:
// ... {value} ...
// ... -{name} ...
// ... -{name}={value} ...
// ... -{name}== {value} ... < parameter group
// ... -{name}=== {value to end} < parameter group to the end of parameter block
// ... "-{value}" ... < escaped command prefix will be ignored
//
// names and values can be escaped with "
// ... "{val ue}" ...
// ... -"{na me}" ...
// ... -{name}="{val ue}" ...
// ... -"{na me}"={value} ...
// ... -"{na me}"="{val ue}" ...
// ... -"{na me}={val ue}" ...
//
// default:
// CommandLine the command line with which the program was started
// CommandPrefix - and /
// ValueSeperator = and :
// CaseSensitive False
// LowerCaseParams False
// TrimParams False

TParameterProc = Function(Index: Integer; Name, Value, ValueEOP: String): Boolean of Object;
TParameter = Record
Strict Private
  ...
Public
  Class Function GetDefault: TParameter; Static;

  Procedure SetCommandLine(S: String; IncludingApp: Boolean = True);
  Property Application: String Read GetApp;
  Function ParamCount: Integer;
  Property Param [idx: Integer]: String Index 0 Read GetParam;
  Property ParamLC [idx: Integer]: String Index 1 Read GetParam;
  Property ParamEOP[idx: Integer]: String Index 2 Read GetParam;

  Property CommandPrefix: Char Index 0 Read GetChar Write SetChar; // #0 if not used
  Property ValueSeperator: Char Index 1 Read GetChar Write SetChar; //
  Property CommandPrefix2: Char Index 2 Read GetChar Write SetChar; //
  Property ValueSeperator2: Char Index 3 Read GetChar Write SetChar; //
  Property CaseSensitive: Boolean Index 0 Read GetBool Write SetBool;
  Property LowerCaseParams: Boolean Index 1 Read GetBool Write SetBool;
  Property TrimParams: Boolean Index 2 Read GetBool Write SetBool;

  Property Exists [Name: String]: Boolean Read GetExists;
  Property Value [Name: String]: Variant Index 0 Read GetValue; Default;
  Property ValueLC [Name: String]: Variant Index 1 Read GetValue;
  Property ValueEOP[Name: String]: Variant Index 2 Read GetValue;
  Function IndexOf (Name: String): Integer;
  Property Name [idx: Integer]: String Index 3 Read GetParam;

  Function Parse(Proc: TParameterProc): Integer; // if Proc retunt FALSE then parsing is stopped

  Function GetModule: String;
  Function GetModulePath: String;
  Property GetCall: String Read FCommandLine;
End;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat