delphi - 在Delphi XE5中使用FileGetSymLinkTarget不会返回它指向的网络地址

标签 delphi file-link

我正在使用 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 的示例创建了一个例程,该例程返回本地驱动器和网络路径的正确符号链接(symbolic link)路径。虽然我现在调用此例程来代替 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;

最佳答案

以下内容在我的测试设置中有效,它使用 GetFinalPathNameByHandle .

var
  LinkHandle: THandle;
  TargetName: array [0..512] of Char;
begin
  LinkHandle := CreateFile('[path to sym link]', 0, FILE_SHARE_READ, nil,
      OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  Win32Check(LinkHandle <> INVALID_HANDLE_VALUE);
  try
    if GetFinalPathNameByHandle(LinkHandle, TargetName, 512,
        FILE_NAME_NORMALIZED) > 0 then
      ShowMessage(TargetName)
    else
      RaiseLastOSError;
  finally
    CloseHandle(LinkHandle);
  end;

end;

目标路径显示为\\?\UNC\Server\Share\Folder\SubFolder\。您可以再次测试最左侧的 \\?\UNC 并根据需要将其替换为 \

您还可以用 VOLUME_NAME_NONE 代替 FILE_NAME_NORMALIZED,以使目标路径为 \Server\Share\Folder\SubFolder\

RTL 在其一次尝试中使用相同的函数,以 VOLUME_NAME_NT 作为结果类型,返回类似 Device\Mup\.. 的路径,然后尝试匹配具有本地逻辑卷之一的字符串的起始部分 (GetLogicalDriveStrings)。当没有匹配项时,由于路径指向网络驱动器,因此它会返回一个空字符串,正如您所注意到的。


请注意 RTL 源中有关跨机器边界的符号链接(symbolic link)的注释:

The access rights of symlinks are unpredictable over network drives. It is therefore not recommended to create symlinks over a network drive. To enable remote access of symlinks under Windows Vista and Windows 7 use the command: "fsutil behavior set SymlinkEvaluation R2R:1 R2L:1"

关于delphi - 在Delphi XE5中使用FileGetSymLinkTarget不会返回它指向的网络地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23409775/

相关文章:

security - 文件 URI 链接到 IE7 中的本地文件夹不起作用

Delphi:关闭应用程序时如何调试访问冲突?

c# 使用正则表达式更改文件链接路径

filesystems - FAT32 格式存储上的文件系统链接

javascript - 为什么 OnUserAuthenticate 在 DataSnap REST 服务器上被调用两次?

jupyter - 创建指向 Google Colab jupyter 笔记本中动态生成的文件的文件下载链接

delphi - 将光标置于错误的 Tedit 文本 Delphi

delphi - 一次发送多于 2 行的问题

delphi - 如何将单元中定义的组件添加到Delphi调色板?