Delphi 系统文件功能的跨平台系统实用程序
Delphi cross-platform system utilities for system file functions
我正在将 Delphi 10.3 VCL 应用程序迁移到 Firemonkey。不使用 GUI 的单元无需任何修改即可编译,但使用下面提到的 Windows-特定系统函数的单元除外。
任何人都可以指出 Delphi/Firemonkey 10.3 中的跨平台系统文件实用程序或替代解决方法,以执行完成我的项目所需的以下操作:
根据扩展名或 MIME 类型提取文件或应用程序的系统图标
执行系统shell命令,例如打开一个文件(相当于 WinAPI ShellExecute
)
在子进程中启动外部程序并等待其终止(例如,使用 WinAPI CreateProcess
创建子进程并使用 WaitForSingleObject
等待)
Get/set 文件的 TimeCreated、TimeModified 和 TimeAccessed 时间戳,以便可以制作与源文件具有相同时间戳的文件副本。
我有 Googled 个,但我看到的命中率仅涉及 Windows 个函数。一些点击表明 Free Pascal 提供了 TProcess
class 和 ExecuteProcess()
、RunCommand()
和 OpenDocument()
过程,这些过程被描述为跨平台的。
关于时间戳,可以使用 FindFirst
和 FindNext
函数获取这些时间戳,然后在返回的 TSearchRec
中读取时间戳。但是我没有找到如何在 FMX 版本中设置时间戳,这是我在 VCL 版本中使用相关的 Win API 函数完成的。
我不是在征求关于多个可能选项中最佳选项的意见或建议,而是针对有关 Delphi 10.3 对基本系统功能的跨平台支持的特定问题的事实回答人们希望在任何成熟的 GUI OS 中找到它,例如 Windows 和基于 Unix 的 OS。在将问题发布到 Whosebug 之前,我在 Delphi 帮助系统和 Google 上搜索了答案但没有成功。该线程中的第一个答案就是这样做的。我很感激。
你问的四点在我看来对于一个问题来说差异太大了。
对于最后一点,您在单元 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);
对于您的第 1 点到第 3 点,Delphi 的 RTL 中还没有解决方案。
对于你的第 2 点和第 3 点,我已经实现了我自己的适用于 Windows 和 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;
对于最终解决方案,您必须检查并处理 API 函数 ShellExecute
和 System
.
的结果
关于你的第一点,我有一个解决方案只适用于 windows:
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;
我正在将 Delphi 10.3 VCL 应用程序迁移到 Firemonkey。不使用 GUI 的单元无需任何修改即可编译,但使用下面提到的 Windows-特定系统函数的单元除外。
任何人都可以指出 Delphi/Firemonkey 10.3 中的跨平台系统文件实用程序或替代解决方法,以执行完成我的项目所需的以下操作:
根据扩展名或 MIME 类型提取文件或应用程序的系统图标
执行系统shell命令,例如打开一个文件(相当于 WinAPI
ShellExecute
)在子进程中启动外部程序并等待其终止(例如,使用 WinAPI
CreateProcess
创建子进程并使用WaitForSingleObject
等待)Get/set 文件的 TimeCreated、TimeModified 和 TimeAccessed 时间戳,以便可以制作与源文件具有相同时间戳的文件副本。
我有 Googled 个,但我看到的命中率仅涉及 Windows 个函数。一些点击表明 Free Pascal 提供了 TProcess
class 和 ExecuteProcess()
、RunCommand()
和 OpenDocument()
过程,这些过程被描述为跨平台的。
关于时间戳,可以使用 FindFirst
和 FindNext
函数获取这些时间戳,然后在返回的 TSearchRec
中读取时间戳。但是我没有找到如何在 FMX 版本中设置时间戳,这是我在 VCL 版本中使用相关的 Win API 函数完成的。
我不是在征求关于多个可能选项中最佳选项的意见或建议,而是针对有关 Delphi 10.3 对基本系统功能的跨平台支持的特定问题的事实回答人们希望在任何成熟的 GUI OS 中找到它,例如 Windows 和基于 Unix 的 OS。在将问题发布到 Whosebug 之前,我在 Delphi 帮助系统和 Google 上搜索了答案但没有成功。该线程中的第一个答案就是这样做的。我很感激。
你问的四点在我看来对于一个问题来说差异太大了。
对于最后一点,您在单元 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);
对于您的第 1 点到第 3 点,Delphi 的 RTL 中还没有解决方案。
对于你的第 2 点和第 3 点,我已经实现了我自己的适用于 Windows 和 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;
对于最终解决方案,您必须检查并处理 API 函数 ShellExecute
和 System
.
关于你的第一点,我有一个解决方案只适用于 windows:
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;