Search code examples
windowsdelphidelphi-2007shortcutmaxlength

Do Windows shortcuts support very long argument lengths?


I am trying to create a shortcut (on the Desktop) that contains a long argument string (> MAX_PATH).

The MSDN documentation clearly states that for Unicode string the string can be longer than MAX_PATH.

The resulting shortcut is cut exactly after MAX_PATH characters (that is the Path + the Arguments).

Is there something wrong with my implementation or is this some Windows limitation?

procedure CreateShortcut(APath: WideString;
  AWorkingDirectory: WideString; AArguments: WideString; ADescription: WideString;
  ALinkFileName: WideString);
var
   IObject : IUnknown;
   ISLink  : IShellLinkW;
   IPFile  : IPersistFile;
begin
   IObject := CreateComObject(CLSID_ShellLink);
   ISLink := IObject as IShellLinkW;
   ISLink.SetPath(            PWideChar(APath));
   ISLink.SetWorkingDirectory(PWideChar(AWorkingDirectory));
   ISLink.SetArguments(       PWideChar(AArguments));
   ISLink.SetDescription(     PWideChar(ADescription));
   IPFile := IObject as IPersistFile;
   IPFile.Save(PWideChar(ALinkFileName), False);
end;

PS: OS is Windows XP (and above).


Solution

  • It turns out that this issue is in fact solely a limitation in the Explorer shell dialog. The generated shortcut file does not have a 260 character limitation. It's simply that the dialog refuse to display a Target with more characters than that. Presumably it calls GetPath with a fixed length buffer.

    procedure TForm11.Button1Click(Sender: TObject);
    var
      sl: IShellLinkW;
      pf: IPersistFile;
    begin
      CoCreateInstance(CLSID_ShellLink, nil, 
        CLSCTX_INPROC_SERVER, IID_IShellLinkW, sl);
      sl.SetPath('c:\desktop\test.bat');
      sl.SetWorkingDirectory('c:\desktop\');
      sl.SetArguments(PChar(StringOfChar('x', 300)+'_the_end'));
      pf := sl as IPersistFile;
      pf.Save('c:\desktop\test.lnk', False);
    end;
    

    My test.bat looks like this:

    echo %1> test.out
    

    The resulting test.out goes right the way to _the_end!