ファイルが本物かシンボリックリンクかをC#を使用して判断する方法はありますか?
私はMSDNW32ドキュメント( http://msdn.Microsoft.com/en-us/library/aa364232(VS.85).aspx )を調べましたが、何も見つかりませんこれをチェックします。ここからCreateSymbolicLinkを使用していますが、正常に機能しています。
私はいくつかの 私のブログに投稿されたシンボリックリンクのソースコード を持っています。
また、拡張したいNUnitテストケースも含まれています。
肉のビットは次のとおりです。
_private static SafeFileHandle getFileHandle(string path)
{
return CreateFile(path, genericReadAccess, shareModeAll, IntPtr.Zero, openExisting,
fileFlagsForOpenReparsePointAndBackupSemantics, IntPtr.Zero);
}
public static string GetTarget(string path)
{
SymbolicLinkReparseData reparseDataBuffer;
using (SafeFileHandle fileHandle = getFileHandle(path))
{
if (fileHandle.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
int outBufferSize = Marshal.SizeOf(typeof(SymbolicLinkReparseData));
IntPtr outBuffer = IntPtr.Zero;
try
{
outBuffer = Marshal.AllocHGlobal(outBufferSize);
int bytesReturned;
bool success = DeviceIoControl(
fileHandle.DangerousGetHandle(), ioctlCommandGetReparsePoint, IntPtr.Zero, 0,
outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero);
fileHandle.Close();
if (!success)
{
if (((uint)Marshal.GetHRForLastWin32Error()) == pathNotAReparsePointError)
{
return null;
}
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
reparseDataBuffer = (SymbolicLinkReparseData)Marshal.PtrToStructure(
outBuffer, typeof(SymbolicLinkReparseData));
}
finally
{
Marshal.FreeHGlobal(outBuffer);
}
}
if (reparseDataBuffer.ReparseTag != symLinkTag)
{
return null;
}
string target = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer,
reparseDataBuffer.PrintNameOffset, reparseDataBuffer.PrintNameLength);
return target;
}
_
あれは:
CreateFile()
でファイルを開きますDeviceIoControl()
を呼び出して、再解析ポイントデータを取得します(注:ジャンクションポイントである可能性があります!)private bool IsSymbolic(string path)
{
FileInfo pathInfo = new FileInfo(path);
return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
これは、ファイルとディレクトリをファイルへのリンクとディレクトリへのリンクから区別する例です。
ファイルまたはディレクトリへのリンクは、ターゲットとは別に独自の属性(作成日、権限)を維持します。
ターゲットファイルに影響を与えることなく、ファイルリンクを削除できます(「del」を使用するなど)。
ターゲットディレクトリに影響を与えることなく、ディレクトリリンク(「rmdir」など)を削除できます。 「rd/s」を使用するときは注意してください。これにより、ディレクトリリンクターゲットが削除されます。
FileAttributes
とFileInfo
の両方をチェックインするためのキーDirectoryInfo
フラグはFileAttributes.ReparsePoint
。
static void Main( string[] args ) {
FileInfo file_info = new FileInfo(args[0]);
DirectoryInfo directory_info = new DirectoryInfo(args[0]);
bool is_file = file_info.Exists;
bool is_directory = directory_info.Exists;
if (is_file) {
Console.WriteLine(file_info.ToString() + " is a file");
if ( file_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows file link");
}
else if (is_directory) {
Console.WriteLine(directory_info.ToString() + " is a directory");
if ( directory_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows directory link");
}
スタックオーバーフローの質問に対する この回答 によるとファイルがPowerShellのシンボリックリンクであるかどうかを確認します。 ( File.GetAttributes を介して)ファイルの System.IO.FileAttributes を取得し、ReparsePointビットをテストすると機能します。ビットが設定されている場合、それはシンボリックリンクまたはジャンクションポイントです。そうでない場合は、通常のファイル(またはハードリンク)です。
上記の答えが信頼できないことを証明しています。最後に、私は [〜#〜] msdn [〜#〜] から正しい解決策を得ました:
指定されたディレクトリがマウントされたフォルダであるかどうかを判断するには、最初にGetFileAttributes関数を呼び出し、戻り値のFILE_ATTRIBUTE_REPARSE_POINTフラグを調べて、ディレクトリに再解析ポイントが関連付けられているかどうかを確認します。含まれている場合は、FindFirstFile関数とFindNextFile関数を使用して、WIN32_FIND_DATA構造体のdwReserved0メンバーの再解析タグを取得します。再解析ポイントがマウントされたフォルダーであるかどうかを判断するには(他の形式の再解析ポイントではない)、タグの値が値IO_REPARSE_TAG_MOUNT_POINTと等しいかどうかをテストします。詳細については、「ポイントの再解析」を参照してください。
GetFileInformationByHandleBY_HANDLE_FILE_INFORMATION フィールドdwFileAttributes
を持つ構造を埋めます。ここで、ビットはファイルの属性に関する情報で設定されます(詳細 ここ ) 。特に、マスクのビットを見てください...:
FILE_ATTRIBUTE_REPARSE_POINT
1024 0x0400再解析ポイントが関連付けられているファイルまたはディレクトリ、またはシンボリックリンクであるファイル。