检查文件是真实的还是符号链接
有没有办法告诉使用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”时要小心。 这将删除目录链接目标。
用于检入FileInfo
和DirectoryInfo
的密钥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。 有关更多信息,请参阅重新分析点。