Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delphi get folder path

I m working with Delphi 7 and I want to find out the path of my .. /All Users/Documents directory.
I came across the following code

uses shlobj, ...

function GetMyDocuments: string;
 var
  r: Bool;
  path: array[0..Max_Path] of Char;
 begin
  r := ShGetSpecialFolderPath(0, path, CSIDL_Personal, False) ;
  if not r then 
    raise Exception.Create('Could not find MyDocuments folder location.') ;
  Result := Path;
 end;

It works fine but it does not support CSIDL_COMMON_DOCUMENTS which returns the desired path.

Moreover as per MS CSIDL should no longer be used instead use KNOWNFOLDERID .
And I do need to work this app on multiple OS's (only windows).

How can I do this ?
Help is appreciated :)

like image 377
Shirish11 Avatar asked Jan 03 '12 13:01

Shirish11


3 Answers

In my view there's nothing wrong with calling SHGetSpecialFolderPath passing CSIDL_COMMON_DOCUMENTS. If you need to support XP then you can't use known folder IDs. You could write code that used known folder IDs on Vista and up, and fell back to CSIDL on earlier systems. But why bother? MS have done that for you with SHGetSpecialFolderPath.

like image 114
David Heffernan Avatar answered Oct 21 '22 21:10

David Heffernan


As David already stated, use the SHGetSpecialFolderPath function. Vista and W7 will do the CSIDL/Folder conversion for you. If you want to use the newer API, This should to the trick: Please note that this will only work from vista.

unit Unit1;

interface

uses
  Windows, ActiveX, Forms, SysUtils, OleAuto, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


type
 TShGetKnownFolderPath = function(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function ShGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult;

var Shell: HModule;
    Fn: TShGetKnownFolderPath;

begin
 Shell := LoadLibrary('shell32.dll');
 Win32Check(Shell <> 0);
 try
  @Fn := GetProcAddress(Shell, 'SHGetKnownFolderPath');
  Win32Check(Assigned(Fn));
  Result := Fn(rfid, dwFlags, hToken, ppszPath);
 finally
  FreeLibrary(Shell);
 end;
end;

function GetPublicDocuments: string;
 var
  ret: HResult;
  Buffer: PWideChar;
begin
  ret := ShGetKnownFolderPath(StringToGuid('{ED4824AF-DCE4-45A8-81E2-FC7965083634}'), 0, 0, Buffer) ;
  OleCheck(ret);
  try
   Result := Buffer;
  finally
    CoTaskMemFree(Buffer);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ShowMessage(GetPublicDocuments);
end;

end.
like image 2
whosrdaddy Avatar answered Oct 21 '22 22:10

whosrdaddy


Aren't you supposed to use ShGetFolderPath from shell32.dll? This assumes using windows 2000 with IE5 or newer.

you need to add shlobj to the uses line for the code that makes use of it.

As there is no definition for SHGetFolderPath in the source, you can use the following before the code that uses it:

function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: PChar): HResult; stdcall; external 'shfolder.dll' name 'SHGetFolderPathA';

Delphi 7 does not make use of the Wide version of the routine, so you can use this code.

like image 4
Petesh Avatar answered Oct 21 '22 21:10

Petesh