检查文件是真实的还是符号链接

有没有办法告诉使用C#文件是真实的还是符号链接?

我已经挖掘了MSDN W32文档( 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”时要小心。 这将删除目录链接目标。

用于检入FileInfoDirectoryInfo的密钥FileAttributes标志是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"); } 

根据Stack Overflow问题的答案 找出文件是否是PowerShell中的符号链接 ,获取文件的System.IO.FileAttributes (通过File.GetAttributes ),并测试ReparsePoint位,是有效的。 如果设置了该位,则它是符号链接连接点。 如果没有,它是一个常规文件(或硬链接)。

GetFileInformationByHandle填充BY_HANDLE_FILE_INFORMATION结构,该结构具有字段dwFileAttributes ,其中位设置有关于文件属性的信息(详情请参见此处 )。 特别是,看掩码……:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

具有关联重分析点的文件或目录,或者是符号链接的文件。

它certificate了上述答案并不可靠。 最后我从MSDN获得了正确的解决方案:

要确定指定的目录是否为已装入的文件夹,请首先调用GetFileAttributes函数并检查返回值中的FILE_ATTRIBUTE_REPARSE_POINT标志,以查看该目录是否具有关联的重新分析点。 如果是,请使用FindFirstFile和FindNextFile函数获取WIN32_FIND_DATA结构的dwReserved0成员中的重新分析标记。 要确定重新分析点是否为已装入的文件夹(而不是其他forms的重新分析点),请测试标记值是否等于值IO_REPARSE_TAG_MOUNT_POINT。 有关更多信息,请参阅重新分析点。