我正在使用 Delphi XE5 和 XE6,并通过对提示提升和使用 Delphi 函数的进程进行外壳处理以编程方式创建许多目录链接:
FileCreateSymLink( sLinkPath, sTargetPath )
从现在开始,我对 sLinkPath 的使用被文件系统自动引导到 sTarget 路径。这一切都很好。在其他时候,我还需要询问这样的链接以查看 (a) 它是否是链接以及 (b) 它指向的位置。为此,我调用 Delphi 函数
function FileGetSymLinkTarget(const FileName: string; var TargetName: string): Boolean;
通过成功创建指向本地硬盘上另一个文件夹的链接,这可以正常工作。但是,当我创建指向网络位置的链接时,例如
\\SERVER\Working\scratch\BJF\test
该链接在文件系统级别完美运行,但 Delphi 调用 FileGetSymLinkTarget 返回 false 和空目标字符串。进入 SysUtils.pas 会显示对“InternalGetFileNameFromSymLink”的调用,这反过来会显示很多人挥手“尝试”各种调用以获取合理的目标信息。我注意到在这个例程中,成功的一次尝试是调用
GetObjectInfoName(Handle)
哪个回报
\Device\Mup\SERVER\Working\scratch\BJF\test
(关闭!)但随后被 ExpandVolumeName 删除,可能是因为前缀,为空字符串。
所以,我的问题是:
这可能是 XE5 和 XE6 中的错误吗?是否有其他方法可以在不使用 SysUtils 的情况下读取链接目标?
以后根据接受的答案添加:
我根据 Sertac 的示例创建了如下例程,该例程为本地驱动器和网络路径返回正确的符号链接路径。尽管我现在调用此例程来代替 SysUtils.FileGetSymLinkTarget,但首先调用 SysUtils.FileGetSymLinkTarget 并且仅在返回的目标为空时才使用我的例程可能很有用,也许是为了应对我没有尝试过的重定向。
function MyFileGetSymLinkTarget( const APathToLink : string; var ATarget : string ) : boolean;
var
LinkHandle: THandle;
TargetName: array [0..OFS_MAXPATHNAME-1] of Char;
begin
ATarget := '';
LinkHandle := CreateFile( PChar(APathToLink), 0, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
Win32Check(LinkHandle <> INVALID_HANDLE_VALUE);
try
Result := GetFinalPathNameByHandle(LinkHandle, TargetName, OFS_MAXPATHNAME, FILE_NAME_NORMALIZED) > 0;
if Result then
begin
ATarget := TargetName;
if Pos( '\\?\UNC\', ATarget ) = 1 then
begin
Delete( ATarget, 1, 8 );
Insert( '\\', ATarget, 1 );
end
else
if Pos( '\\?\', ATarget ) = 1 then
Delete( ATarget, 1, 4 );
end;
finally
CloseHandle(LinkHandle);
end;
end;