私は 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
リンクはファイル システム レベルで完全に機能しますが、FileGetSymLinkTarget への Delphi 呼び出しは false と null ターゲット文字列を返します。SysUtils.pas に足を踏み入れると、「InternalGetFileNameFromSymLink」への呼び出しが明らかになり、適切なターゲット情報を取得するためにさまざまな呼び出しを「試行」するために手を振っていることが明らかになります。このルーチン内で成功する 1 つの試行は、への呼び出しであることに気付きました
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;