如果文件是真实的或符号链接,有没有办法告诉使用C#?
我已经挖掘了MSDN W32文档(http://msdn.microsoft.com/en-us/library/aa364232(VS.85).aspx),但找不到任何可以检查的内容。我从这里使用CreateSymbolicLink,它工作正常。
答案 0 :(得分:27)
private bool IsSymbolic(string path)
{
FileInfo pathInfo = new FileInfo(path);
return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
答案 1 :(得分:21)
我有一些source code for symlinks posted on my blog可以让您:
它还包含您可能希望扩展的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()
获取重新分析点数据(注意:它可能是一个交接点!)答案 2 :(得分:7)
以下是将文件和目录与文件链接和目录链接区分开来的示例。
指向文件或目录的链接将其自己的属性(创建日期,权限)与其目标分开。
可以删除文件链接(例如使用“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");
}
答案 3 :(得分:1)
根据this answer到Stack Overflow问题查看文件是否是PowerShell中的符号链接,获取文件的System.IO.FileAttributes(通过File.GetAttributes ),并测试ReparsePoint位,工作。如果设置了该位,则符号链接或是一个连接点。如果没有,它是一个常规文件(或硬链接)。
答案 4 :(得分:0)
GetFileInformationByHandle填充BY_HANDLE_FILE_INFORMATION结构,其中包含字段dwFileAttributes
,其中的位设置有关于文件属性的信息(详情here)。特别是,看掩码......:
FILE_ATTRIBUTE_REPARSE_POINT
1024 0x0400具有的文件或目录 关联的重新分析点或文件 这是一个象征性的联系。
答案 5 :(得分:0)
证明以上答案不可靠。 最后,我从MSDN得到了正确的解决方案:
要确定指定的目录是否为已安装的文件夹,请首先调用GetFileAttributes函数并检查返回值中的FILE_ATTRIBUTE_REPARSE_POINT标志,以查看该目录是否具有关联的重解析点。如果是这样,请使用FindFirstFile和FindNextFile函数在WIN32_FIND_DATA结构的dwReserved0成员中获取reparse标签。要确定重新解析点是否是已安装的文件夹(而不是某种其他形式的重新解析点),请测试标记值是否等于值IO_REPARSE_TAG_MOUNT_POINT。有关更多信息,请参见重新解析点。
答案 6 :(得分:0)
库MonoPosix提供API来检查文件是否为符号链接:
public bool IsSymlink(string filePath)
=> UnixFileSystemInfo.GetFileSystemEntry(filePath).IsSymbolicLink;
答案 7 :(得分:0)
我知道我晚会晚了,但是在研究相同问题时发现了这一讨论
我发现以下内容对我有用,因此我认为我可以在其他人使用的情况下发布
它的工作原理是这样的:-
var provider = ReparsePointFactory.Provider;
var link = provider.GetLink(@"c:\program files (x86)\common files\microsoft shared\vgx\vgx.dll");
MsgBox("Link Type: " + link.Type.ToString + " Link Target: " + link.Target + " Link Attributes: " + link.Attributes.ToString);
https://github.com/NCodeGroup/NCode.ReparsePoints https://www.nuget.org/packages/NCode.ReparsePoints/