Проверьте, является ли файл реальным или символическая ссылка

Есть ли способ сказать, используя С#, если файл является реальным или символической ссылкой?

Я прорыл документы MSDN W32 (http://msdn.microsoft.com/en-us/library/aa364232(VS.85).aspx) и не могу найти что-либо для проверки этого. Я использую CreateSymbolicLink отсюда, и он отлично работает.

Ответ 1

У меня есть исходный код для символических ссылок, опубликованных в моем блоге, который позволит вам:

  • создать символические ссылки
  • проверить, является ли путь символической ссылкой
  • получить цель символической ссылки

Он также содержит тестовые примеры 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

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

Ответ 3

Вот пример различения файлов и каталогов из ссылок на файлы и ссылки на каталоги.

Связи с файлами или каталогами сохраняют свои собственные атрибуты (дату создания, разрешения) отдельно от своих целей.

Ссылки на файлы можно удалить (например, с помощью "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");
}

Ответ 4

В соответствии с этот ответ в вопрос о переполнении стека Узнайте, является ли файл символической ссылкой в ​​PowerShell, получив System.IO.FileAttributes для файла (через File.GetAttributes) и тестирование бит ReparsePoint, работает, Если бит установлен, это символическая ссылка или точка соединения. Если нет, это обычный файл (или жесткая ссылка).

Ответ 5

GetFileInformationByHandle заполняет структуру BY_HANDLE_FILE_INFORMATION, которая имеет поле dwFileAttributes, где биты задаются с информацией об атрибутах файла (подробности здесь). В частности, посмотрите на бит в маске...:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

Файл или каталог, который имеет связанную точку повторной обработки или файл это символическая ссылка.