Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get appdata folder path in delphi

How can I get the appdata folder path? This is my code:

begin
  Winexec(PAnsichar('%appdata%\TEST.exe'), sw_show);
end;

but not working.

like image 791
user3613101 Avatar asked Aug 13 '15 18:08

user3613101


People also ask

How do I find the AppData path?

You can either access it manually or by using the "AppData" variable name. You can view the AppData folder manually by going into your Users folder, which is there in the C drive. In my case, the path is C:\Users\ADMIN . Now you should be able to see the AppData folder in your User folder.

How do I get to AppData from command prompt?

Run a command shell (start/Run, then "cmd") and type "set". This will list all the environmental variables available. Having said that, USERPROFILE is perfectly valid. There's also APPDATA and LOCALAPPDATA.


2 Answers

You cannot pass environment variables to WinExec(). You have to resolve them first, eg:

uses
  ..., SysUtils;

function GetPathToTestExe: string;
begin
  Result := SysUtils.GetEnvironmentVariable('APPDATA');
  if Result <> '' then
    Result := IncludeTrailingPathDelimiter(Result) + 'TEST.exe';
end;
uses
  ..., Windows;

var
  Path: string;
begin
  Path = GetPathToTestExe;
  if Path <> '' then
    WinExec(PAnsiChar(Path), SW_SHOW);
end;

Alternatively:

uses
  ..., SysUtils, Windows;

function GetPathToTestExe: string;
var
  Path: array[0..MAX_PATH+1] of Char;
begin
  if ExpandEnvironmentStrings('%APPDATA%', Path, Length(Path)) > 1 then
    Result := IncludeTrailingPathDelimiter(Path) + 'TEST.exe'
  else
    Result := '';
end;

A more reliable (and official) way to get the APPDATA folder path is to use SHGetFolderPath() (or SHGetKnownFolderPath() on Vista+) instead, eg:

uses
  ..., SysUtils, Windows, SHFolder;

function GetPathToTestExe: string;
var
  Path: array[0..MAX_PATH] of Char;
begin
  if SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, Path) = S_OK then
    Result := IncludeTrailingPathDelimiter(Path) + 'TEST.exe'
  else
    Result := '';
end;

Alternatively:

uses
  ..., SysUtils;

function GetPathToTestExe: string;
var
  Path: string;
begin
  // GetHomePath() uses SHGetFolderPath(CSIDL_APPDATA) internally...
  Path := SysUtils.GetHomePath;
  if Path <> '' then
    Result := IncludeTrailingPathDelimiter(Path) + 'TEST.exe'
  else
    Result := '';
end;

But, in any case, WinExec() has been deprecated since Windows 95, you really should be using CreateProcess() instead, eg:

uses
  ..., Windows;

var
  Path: String;
  si: TStartupInfo;
  pi: TProcessInformation;

Path := GetPathToTestExe;
if Path <> '' then
begin
  ZeroMemory(@si, SizeOf(si));
  si.cb := SizeOf(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := SW_SHOW;

  if CreateProcess(nil, PChar(Path), nil, nil, FALSE, 0, nil, nil, @si, pi)
  begin
    //...
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
  end;
end;
like image 95
Remy Lebeau Avatar answered Oct 05 '22 13:10

Remy Lebeau


The proper way to do it, using System.IOUtils:

function GetAppDataFolder: string;                                       { Returns the path to the current user's AppData folder on Windows and to the current user's home directory on Mac OS X.   Example:  c:\Documents and Settings\Bere\Application Data\AppName\ }
begin
 Assert(System.IOUtils.TPath.HasValidFileNameChars(AppName, FALSE), 'Invalid chars in AppName: '+ AppName);
 Result:= Trail(Trail(System.SysUtils.GetHomePath)+ AppName);
end;

Utils:

function ForceAppDataFolder: string;  // Make sure the AppDataFolder exists before you try to write the INI file there!                                      
begin
 Result:= GetAppDataFolder;
 ForceDirectories(Result);
end;

function Trail(CONST Path: string): string;    //ok  Works with UNC paths
begin
 if Path= '' then EXIT('');                                                                        { Encountered when doing something like this:  ExtractLastFolder('c:\'). ExtractLastFolder will return '' }
 Result:= IncludeTrailingPathDelimiter(Path)
end;
like image 36
Server Overflow Avatar answered Oct 05 '22 12:10

Server Overflow