PDA

View Full Version : get user home directory



{MSX}
20-05-2005, 08:51 AM
Hi! is there a way to retrieve the user home directory?
i've tried something like this:

assign(f, '%USERPROFILE%\test.txt');
rewrite(f);
write(f, 'ciao');
closefile(f);


but it doesn't work..
I'd like something that work for linux too.

Bye!

savage
20-05-2005, 09:54 AM
You should be able to use something like this ( NOTE Untested and thrown together from stuff off the internet )...

uses
ActiveX,
ComObj,
ShlObj;

function GetPersonalPath : string;
var
{$IFDEF WIN32}
shellMalloc: IMalloc;
ppidl: PItemIdList;
PerDir: string;
{$ELSE}
ppwd :PPasswordRecord;
{$ENDIF}
begin
{$IFDEF WIN32}
ppidl := nil;
try
if SHGetMalloc(shellMalloc) = NOERROR then
begin
SHGetSpecialFolderLocation(0, CSIDL_PERSONAL, ppidl);
SetLength(Result, MAX_PATH);
if not SHGetPathFromIDList(ppidl, PChar(Result)) then
raise exception.create('SHGetPathFromIDList failed : invalid pidl');
SetLength(Result, lStrLen(PChar(Result)));
end;
finally
if ppidl <> nil then
shellMalloc.free(ppidl);
end;
{$ELSE}
ppwd := getpwuid( getuid() );
Result := ppwd^.pw_dir;
{$ENDIF}
end;


Keep us posted if you find a better solution?

savage
20-05-2005, 09:55 AM
Btw, for linux you could also use the GetEnvironmentVariable('HOME') method, but that will only work if the environment variable has been set.

{MSX}
20-05-2005, 01:51 PM
I can't find the unit that contains that calls for the Windows part. Can you post them? I hope they exists on FPC..

thanks

JSoftware
20-05-2005, 01:59 PM
shellapi

ahh 6-bit knight :D

savage
20-05-2005, 02:24 PM
Actually, the uses clause you need is...

uses
ActiveX,
ComObj,
ShlObj;


I would be surprised if it does not exist in FPC, and if it does not, it should be fairly easy to add.

savage
20-05-2005, 02:44 PM
After further investigation, another alternative would be...

uses
{$IFDEF WIN32}
ShlObj; // Only one unit, yeah!
{$ELSE}
libc; // Not sure where getpwuid(), getuid() and PPasswordRecord live
{$ENDIF}

function GetPersonalPath : string;
var
{$IFDEF WIN32}
Res: Bool;
Path: array[0..Max_Path] of Char;
{$ELSE}
ppwd :PPasswordRecord;
{$ENDIF}
begin
{$IFDEF WIN32}
Res := ShGetSpecialFolderPath(0, Path, , False);
if not Res then raise Exception.Create(
'Could not determine My Documents path');
Result := Path;
{$ELSE}
ppwd := getpwuid( getuid() );
Result := ppwd^.pw_dir;
{$ENDIF}
end;


NOTE :if you change CSIDL_PERSONAL to CSIDL_APPDATA this will give you the path to where Applications store their data, which for games would be a much better place to store things than in the My Documents folder.

{MSX}
21-05-2005, 12:38 PM
Unluckly the ShlObj of fpc is empty.. :(
So i hacked up this ugly code. I've tested on linux and windows:


{$IFDEF WIN32}
uses windows, Classes, SysUtils;
const NOERROR:integer=0;
CSIDL_APPDATA = $001a;
type IMalloc = interface(IUnknown)
procedure Free(pv: Pointer); stdcall;
end;
PItemIdList=pointer;
function SHGetMalloc(var ppMalloc: IMalloc): HResult; stdcall; external 'shell32.dll';
function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer; var ppidl: PItemIDList): HResult; stdcall; external 'shell32.dll';
function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall; external 'shell32.dll';
{$ELSE}
uses libc;
{$ENDIF}

function GetPersonalPath : string;
var
{$IFDEF WIN32}
shellMalloc: IMalloc;
ppidl: PItemIdList;
PerDir: string;
{$ELSE}
ppwd :PPasswordRecord;
{$ENDIF}
begin
{$IFDEF WIN32}
ppidl := nil;
try
if SHGetMalloc(shellMalloc) = NOERROR then
begin
SHGetSpecialFolderLocation(0, CSIDL_APPDATA,
ppidl);
SetLength(Result, MAX_PATH);
if not SHGetPathFromIDList(ppidl, PChar(Result)) then raise exception.create('SHGetPathFromIDList failed : invalid pidl');
SetLength(Result, lStrLen(PChar(Result)));
end;
finally
if ppidl <> nil then
shellMalloc.free(ppidl);
end;
{$ELSE}
ppwd := getpwuid( getuid() );
Result := ppwd^.pw_dir;
{$ENDIF}
end;

savage
21-05-2005, 01:22 PM
Thanks for letting us know.