Title: Parsing Command Line Parameters with Delphi
Delphi's ParamStr and ParamCount functions are designed to help operate the parameters (command-line arguments) passed to the application.
Due to the way ParamStr function is implemented in Delphi, parameters passed using double quotes ("") will not be parsed correctly (quotes will be removed).
The "CmdLineHelper" unit provides 3 custom Delphi functions to overcome the problem of the RTL's ParamStr implementation.
//original code author: Remy Lebeau (TeamB)
unit CmdLineHelper;
interface
uses windows;
//command line parameters + program path
function GetCommandLine: string;
//number of parameters
function GetParamCount: Integer;
//parameter by index
function GetParamStr(Index: Integer): String;
implementation
function GetCommandLine : string;
begin
result := windows.GetCommandLine;
end;
function GetNextParam(var CmdLine: PChar; Buffer: PChar; Len: PInteger): Boolean;
var
InQuotedStr, IsOdd: Boolean;
NumSlashes, NewLen, cnt: Integer;
begin
Result := False;
if Len nil then Len^ := 0;
if CmdLine = nil then Exit;
while (CmdLine^ and (CmdLine^ #0) do CmdLine := CharNext(CmdLine) ;
if CmdLine^ = #0 then Exit;
InQuotedStr := False;
NewLen := 0;
repeat
if CmdLine^ = '\' then
begin
NumSlashes := 0;
repeat
Inc(NumSlashes) ;
CmdLine := CharNext(CmdLine) ;
until CmdLine^ '\';
if CmdLine^ = '"' then
begin
IsOdd := (NumSlashes mod 2) 0;
NumSlashes := NumSlashes div 2;
Inc(NewLen, NumSlashes) ;
if IsOdd then Inc(NewLen) ;
if Buffer nil then
begin
for cnt := 0 to NumSlashes-1 do
begin
Buffer^ := '\';
Inc(Buffer) ;
end;
if IsOdd then
begin
Buffer^ := '"';
Inc(Buffer) ;
end;
end;
if IsOdd then CmdLine := CharNext(CmdLine) ;
end else
begin
Inc(NewLen, NumSlashes) ;
if Buffer nil then
begin
for cnt := 0 to NumSlashes-1 do
begin
Buffer^ := '\';
Inc(Buffer) ;
end;
end;
end;
Continue;
end;
if CmdLine^ '"' then
begin
if (CmdLine^ and (not InQuotedStr) then Break;
Inc(NewLen) ;
if Buffer nil then
begin
Buffer^ := CmdLine^;
Inc(Buffer) ;
end;
end
else
InQuotedStr := not InQuotedStr;
CmdLine := CharNext(CmdLine) ;
until CmdLine^ = #0;
if Len nil then Len^ := NewLen;
Result := True;
end;
function GetParamCount: Integer;
var
CmdLine: PChar;
begin
Result := 0;
CmdLine := windows.GetCommandLine;
GetNextParam(CmdLine, nil, nil) ;
while GetNextParam(CmdLine, nil, nil) do Inc(Result) ;
end;
function GetParamStr(Index: Integer): String;
var
Buffer: array[0..MAX_PATH] of Char;
CmdLine, P: PChar;
Len: Integer;
begin
Result := '';
if Index then
begin
Len := GetModuleFileName(0, Buffer, MAX_PATH+1) ;
SetString(Result, Buffer, Len) ;
end else
begin
CmdLine := windows.GetCommandLine;
GetNextParam(CmdLine, nil, nil) ;
repeat
Dec(Index) ;
if Index = 0 then Break;
if not GetNextParam(CmdLine, nil, nil) then Exit;
until False;
P := CmdLine;
if GetNextParam(P, nil, @Len) then
begin
SetLength(Result, Len) ;
GetNextParam(CmdLine, PChar(Result), nil) ;
end;
end;
end;
end.
Note: for testing, you can pass the parameter from the IDE under Run-Parameters menu option.
The screen shot displays the output when the application is called using:
/about delphi "programming" 123.45 67,89
Drop a TMemo ("Memo1") on a Delphi form. Here's a sample usage of the "CmdLineHelper" unit:
uses CmdLineHelper;
...
var
idx : integer;
begin
with Memo1.Lines do
begin
Clear;
Add('CMD Line: ' + CmdLineHelper.GetCommandLine + #13#10) ;
Add('Number of params: ' + IntToStr(CmdLineHelper.GetParamCount) + #13#10) ;
for idx := 1 to CmdLineHelper.GetParamCount do
begin
Memo1.Lines.Add(CmdLineHelper.GetParamStr(idx)) ;
end;
end;
end;