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

时间:2009-09-28 02:36:35

标签: c# symlink

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

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

8 个答案:

答案 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;
}

那是:

答案 2 :(得分:7)

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

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

可以删除文件链接(例如使用“del”)而不影响目标文件。

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

FileAttributesFileInfo签入的密钥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/