The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 4,262 other subscribers

Archive for July 14th, 2011

Delphi commandline oddity with double-quoted arguments

Posted by jpluimers on 2011/07/14

Boy, I was wrong. Somewhere in the back of my head I knew it.

ParamStr goes from zero (the name of the EXE) through ParamCount (the last parameter). Duh :)

 

I’ll keep this so you can have a good laugh:

 

When you add double quoted arguments to the commandline of your Delphi app, strange things can happen: the first parameter seems to be gone, while it is there.

It appears that the ParamCount/ParamStr logic fails here, and cannot be repaired because of backward compatibility.

Lets look at this commandline:

“..\bin\DumpCommandLine.exe” “C:\Program Files\test.xml” “C:\Program Files\meMySelfAndI.xml”

The demo code below will output something like this:

ParamCount:     2
ParamStr():
0       C:\develop\DumpCommandLine\bin\DumpCommandLine.exe
1       C:\Program Files\test.xml
CommandLine:
"..\bin\DumpCommandLine.exe" "C:\Program Files\test.xml" "C:\Program Files\meMySelfAndI.xml"
CommandLineStrings.Count:       3
CommandLineStrings[]:
0       ..\bin\DumpCommandLine.exe
1       C:\Program Files\test.xml
2       C:\Program Files\meMySelfAndI.xml

You see that regular ParamCount/ParamStr calls will mis the “C:\Program Files\test.xml” parameter.
But getting it through CommandLineStrings will correctly get it.

This is the dump code:

unit CommandlineDemoUnit;

interface

procedure DumpCommandLineToConsole;

implementation

uses
  Classes, CommandlineUnit;

procedure DumpCommandLineToConsole;
var
  CommandLineStrings: TStrings;
  I: Integer;
begin
  Writeln('ParamCount:', #9, ParamCount);
  Writeln('ParamStr():');
  for I := 0 to ParamCount - 1 do
    Writeln(I, #9, ParamStr(I));
  Writeln('CommandLine:');
  Writeln(CommandLine);
  CommandLineStrings := CreateCommandLineStrings();
  Writeln('CommandLineStrings.Count:', #9, CommandLineStrings.Count);
  Writeln('CommandLineStrings[]:');
  try
    for I := 0 to CommandLineStrings.Count - 1 do
      Writeln(I, #9, CommandLineStrings[I]);
  finally
    CommandLineStrings.Free;
  end;
end;

end.

And this the code to get the CommandLine and CommandLineStrings, which will fill a TStrings result using the CommaText property (it uses a default QuoteChar of of double quote #34 and Delimiter of space #32, this will work nicely):

unit CommandlineUnit;

interface

uses
  Classes;

function CommandLine: string;
function CreateCommandLineStrings: TStrings;

implementation

uses
  Windows;

function CommandLine: string;
begin
  Result := GetCommandLine();
end;

function CreateCommandLineStrings: TStrings;
begin
  Result := TStringList.Create();
  Result.CommaText := CommandLine;
end;

end.

Note that you need to manually free the TStrings object to avoid memory leaks.

–jeroen

Posted in Delphi, Development, Software Development | 13 Comments »