I am migrating a Delphi 10.3 VCL application to Firemonkey. The units that do not use the GUI compile without any modification except for those which use the Windows-specific system functions mentioned below.
Can anyone point me to cross-platform system file utilities in Delphi/Firemonkey 10.3, or alternative workarounds, to carry out the following actions needed to complete my project:
Extract the system icon for a file or application on the basis of its extension or MIME type
Execute a system shell command, e.g. to open a file (equivalent to WinAPI ShellExecute
)
Launch an external program in a child process and wait for its termination (e.g. create a child process using WinAPI CreateProcess
and wait using WaitForSingleObject
)
Get/set a file’s TimeCreated, TimeModified, & TimeAccessed timestamps so that a file copy may be made having the same timestamps as the source file.
I have Googled for these but the hits I have seen only refer to Windows functions. Some hits indicate that Free Pascal provides a TProcess
class and ExecuteProcess()
, RunCommand()
, and OpenDocument()
procedures that are described as being cross-platform.
Regarding the timestamps, it is possible to obtain these using the FindFirst
and FindNext
functions and then reading timestamps in the TSearchRec
returned. But I didn't find how to set the timestamps in the FMX version, which I did in the VCL version using relevant Win API functions.
I am not asking for opinions or recommendations about the best out of a number of possible options, but for a factual answer to a specific question about Delphi 10.3's cross-platform support for basic system functions that one would expect to find in any mature GUI OS, such as Windows and Unix-based OS's. I searched for the an answer in the Delphi help system and on Google without success before posting the question on Stackoverflow. The first answer in this thread does just that. That I appreciate.
The four points you are asking are too different for one single question in my view.
For your last point you find the solution in the unit System.IOUtils.TFile
:
class function GetCreationTime(const Path: string): TDateTime;
class procedure SetCreationTime(const Path: string; const CreationTime: TDateTime);
class function GetLastAccessTime(const Path: string): TDateTime;
class procedure SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime);
class function GetLastWriteTime(const Path: string): TDateTime;
class procedure SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime);
For your point 1 to 3, there is yet no solution in Delphi's RTL.
For your point 2 and 3, I have implemented my own solution that is working for Windows and MacOS:
uses
{$IFDEF MSWINDOWS}
WinApi.ShellApi;
{$ENDIF}
{$IFDEF MACOS}
Posix.Stdlib;
{$ENDIF}
class procedure TApiHelpers.OpenFileByOS(const FileName: string);
begin
{$IFDEF MSWINDOWS}
ShellExecute(0, 'open', PChar(FileName), nil, nil, SW_SHOW);
{$ENDIF}
{$IFDEF MACOS}
_system(PAnsiChar(UTF8String('open "' + FileName + '"')));
{$ENDIF}
end;
For a final solution, you have to check and handle the result of the API function ShellExecute
and System
.
For your first point, I have a solution working on windows only:
function GetExtImg(const FileName: string; out ExtImg: IExtractImage): boolean;
var
Desktop, Target: IShellFolder;
PIDL: PItemIDList;
Attr, Eaten: DWORD;
res: HResult;
begin
OleCheck(SHGetDesktopFolder(Desktop));
OleCheck(Desktop.ParseDisplayName(0, nil, PChar(ExcludeTrailingPathDelimiter(ExtractFilePath(FileName))), Eaten, PIDL, Attr));
try
OleCheck(Desktop.BindToObject(PIDL, nil, IShellFolder, Target));
finally
fMalloc.Free(PIDL);
end;
OleCheck(Target.ParseDisplayName(0, nil, PChar(ExtractFileName(FileName)), Eaten, PIDL, Attr));
try
Result := S_OK = Target.GetUIObjectOf(fOwnerForm[0], 1, PIDL, IExtractImage, nil, ExtImg);
finally
fMalloc.Free(PIDL);
end;
end;