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

mat*_*wen 27 c# symlink

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

我已经通过MSDN W32文档(http://msdn.microsoft.com/en-us/library/aa364232(VS.85).aspx)进行了挖掘,并且找不到任何可用于检查的内容.我从这里使用CreateSymbolicLink,它工作正常.

zur*_*fyx 32

private bool IsSymbolic(string path)
{
    FileInfo pathInfo = new FileInfo(path);
    return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
Run Code Online (Sandbox Code Playgroud)

  • 仅仅因为文件具有与之关联的重新分析点并不意味着它是符号链接.重新分析点只是与文件关联的任意一组自定义数据.您需要检查重新分析点数据的ID以确定它是否实际定义了符号链接.只要遇到具有重新分析点的真实文件,这个答案就会给出误报.请看这里:https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v = vs.85).aspx (12认同)
  • 这应该是公认的答案.它简单,简洁,直接回答了这个问题. (3认同)

Tro*_*ons 21

在我的博客发布了一些符号链接的源代码,可以让你:

  • 创建符号链接
  • 检查路径是否为符号链接
  • 检索符号链接的目标

它还包含您可能希望扩展的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;
}
Run Code Online (Sandbox Code Playgroud)

那是:

  • 此代码现在是 [NuGet 包](https://www.nuget.org/packages/SymbolicLinkSupport/) 和 [在 GitHub 上](https://github.com/michaelmelancon/symboliclinksupport)。 (3认同)

小智 9

从 .NET 6 开始,您可以使用: FileSystemInfo.LinkTarget属性

物业描述:

获取位于 中的链接的目标路径FullName,或者null如果此FileSystemInfo实例不表示链接。

例如:

static bool IsSymbolicLink(string path)
{
    FileInfo file = new FileInfo(path);
    return file.LinkTarget != null;
}
Run Code Online (Sandbox Code Playgroud)

  • 这是 .NET 6 中的新功能,现在应该是首选方式。谢谢! (3认同)

小智 8

以下是将文件和目录与文件链接和目录链接区分开的示例.

指向文件或目录的链接将其自己的属性(创建日期,权限)与其目标分开.

可以删除文件链接(例如,使用"del")而不影响目标文件.

可以删除目录链接(例如"rmdir")而不影响目标目录.使用"rd/s"时要小心.这将删除目录链接目标.

关键FileAttributes标志检查两FileInfoDirectoryInfoFileAttributes.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");
}
Run Code Online (Sandbox Code Playgroud)

  • 再次,依靠FileAttributes.ReparsePoint是不够的. (4认同)