delphi get folder path
Asked Answered
T

4

10

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 :)

Tinned answered 3/1, 2012 at 13:9 Comment(0)
W
8

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.

Wolsky answered 3/1, 2012 at 13:40 Comment(2)
I cannot find CSIDL_COMMON_DOCUMENTS deceleration in my Shlobj.pas file.Tinned
It has value $002E you will have to declare the constant in your codeWolsky
H
4

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.

Hiram answered 3/1, 2012 at 13:29 Comment(2)
I have shlobj in my uses clause and I cant find ShGetFolderPath in Delphi 7.Tinned
Ah, ShGetFolderPath is newer than your .dcu - I'll update the answer with a change for your file which should allow it to workHiram
E
3

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.
Ellinger answered 3/1, 2012 at 13:53 Comment(0)
J
2

As recommended by Embarcadero in this doc: VistaUACandDelphi.pdf

Uses SHFolder;

function GetSpecialFolder (CSIDL: Integer; ForceFolder: Boolean = FALSE): string;
CONST SHGFP_TYPE_CURRENT = 0;
VAR i: Integer;
begin
 SetLength(Result, MAX_PATH);
 if ForceFolder
 then ShGetFolderPath(0, CSIDL OR CSIDL_FLAG_CREATE, 0, 0, PChar(Result))= S_ok
 else ShGetFolderPath(0, CSIDL, 0, 0, PChar(Result));
 i:= Pos(#0, Result);
 if i> 0
 then SetLength(Result, pred(i));

 Result:= Trail (Result);
end;

Use it like this:

s:= GetSpecialFolder(CSIDL_LOCAL_APPDATA, true);
Jeth answered 5/12, 2013 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.