Перечислите жесткие ссылки файла (в C#)

StackOverflow https://stackoverflow.com/questions/4193309

  •  11-10-2019
  •  | 
  •  

Вопрос

Я хочу написать программу, которая показывает файлы другого диска с жесткими ссылками. Я хочу, чтобы обе жесткие ссылки были последовательны в имени файла, так и в других вещах, поэтому я должен получить функцию/метод, где я могу перечислить все текущие жесткие ссылки файла.

Так, например:

У меня есть файл c: file.txt и вторая жесткая ссылка на d: file.txt.
Затем я переименован D: file.txt to d: file_new.txt. Теперь я хочу также переименовать жесткую ссылку на диск C.
Поэтому мне нужна функция, которая возвращается для d: file_new.txt, есть следующие жесткие ссылки:
C: file.txt
D: file_new.txt
Тогда я могу переименовать жесткую ссылку на C: Также, чтобы получить d: file_new.txt

Поэтому мне нужно получить все жесткие ссылки физического файла. Или: все жесткие ссылки файла, адресованного жесткой ссылкой.

Надеюсь, кто -нибудь сможет помочь!

Редактировать:

Оливер заметил, что жесткие ссылки не могут быть использованы на разных дисках. Спасибо ... так что я распространен на вопрос: что мне нужно? Соединение точек? Символические ссылки? Это также должно работать с файлами не только с папками!

Это было полезно?

Решение 4

Я нашел решение:

Сначала мне не нужно использовать жесткие ссылки (так как они не могут указывать на другой диск). Вместо этого я должен использовать символические ссылки. Таким образом, у меня есть один жесткий файл на исходном диске и символические ссылки на других дисках с этим файлом. Ограничение - ОС должна быть Vista или новее.

Во -вторых, я должен быть в состоянии выяснить, на что указывает символическая ссылка. Здесь я нашел хороший пример, как узнать информацию, которая мне нужна:http://www.codeproject.com/kb/vista/reparsepointid.aspx

Единственное, что мне не удалось найти все символические ссылки из определенного файла (жесткая ссылка). Я предполагаю, что нет никакого решения для коробки, и я должен повторить все символические ссылки и проверить цель. Но в моем случае это не проблема.

Я надеюсь, что это может помочь другим!

Другие советы

Следующий код должен работать хорошо (первоначально пост Питера Провоста в репозитории PowerShell Code):

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;

namespace HardLinkEnumerator
{
   public static class Kernel32Api
   {
       [StructLayout(LayoutKind.Sequential)]
       public struct BY_HANDLE_FILE_INFORMATION
       {
           public uint FileAttributes;
           public FILETIME CreationTime;
           public FILETIME LastAccessTime;
           public FILETIME LastWriteTime;
           public uint VolumeSerialNumber;
           public uint FileSizeHigh;
           public uint FileSizeLow;
           public uint NumberOfLinks;
           public uint FileIndexHigh;
           public uint FileIndexLow;
       }

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
       static extern SafeFileHandle CreateFile(
           string lpFileName,
           [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
           [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
           IntPtr lpSecurityAttributes,
           [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
           [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
           IntPtr hTemplateFile);

       [DllImport("kernel32.dll", SetLastError = true)]
       static extern bool GetFileInformationByHandle(SafeFileHandle handle, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

       [DllImport("kernel32.dll", SetLastError = true)]
       [return: MarshalAs(UnmanagedType.Bool)]
       static extern bool CloseHandle(SafeHandle hObject);

       [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
       static extern IntPtr FindFirstFileNameW(
           string lpFileName,
           uint dwFlags,
           ref uint stringLength,
           StringBuilder fileName);

       [DllImport("kernel32.dll", SetLastError = true, CharSet=CharSet.Unicode)]
       static extern bool FindNextFileNameW(
           IntPtr hFindStream,
           ref uint stringLength,
           StringBuilder fileName);

       [DllImport("kernel32.dll", SetLastError = true)]
       static extern bool FindClose(IntPtr fFindHandle);

       [DllImport("kernel32.dll")]
       static extern bool GetVolumePathName(string lpszFileName,
           [Out] StringBuilder lpszVolumePathName, uint cchBufferLength);

       [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
       static extern bool PathAppend([In, Out] StringBuilder pszPath, string pszMore);

       public static int GetFileLinkCount(string filepath)
       {
           int result = 0;
           SafeFileHandle handle = CreateFile(filepath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Archive, IntPtr.Zero);
           BY_HANDLE_FILE_INFORMATION fileInfo = new BY_HANDLE_FILE_INFORMATION();
           if (GetFileInformationByHandle(handle, out fileInfo))
               result = (int)fileInfo.NumberOfLinks;
           CloseHandle(handle);
           return result;
       }

       public static string[] GetFileSiblingHardLinks(string filepath)
       {
           List<string> result = new List<string>();
           uint stringLength = 256;
           StringBuilder sb = new StringBuilder(256);
           GetVolumePathName(filepath, sb, stringLength);
           string volume = sb.ToString();
           sb.Length = 0; stringLength = 256;
           IntPtr findHandle = FindFirstFileNameW(filepath, 0, ref stringLength, sb);
           if (findHandle.ToInt32() != -1)
           {
               do
               {
                   StringBuilder pathSb = new StringBuilder(volume, 256);
                   PathAppend(pathSb, sb.ToString());
                   result.Add(pathSb.ToString());
                   sb.Length = 0; stringLength = 256;
               } while (FindNextFileNameW(findHandle, ref stringLength, sb));
               FindClose(findHandle);
               return result.ToArray();
           }
           return null;
       }

   }
}

Может быть, я неправильно понял ваши вопросы, но жесткие ссылки не могут перейти от одной поездки к другому. Они могут существовать только на одном диске.

В рамках .net Framwork нет поддержки, чтобы получить эту информацию. Но API Win32 может предоставить вам эту информацию.

Взгляни на эта статья. Анкет Это может помочь вам.

Обновлять

Насколько я знаю, невозможно сделать это между различными дисками. Точки соединения определенно не ваш друг, потому что это работает только на складках. Но после прочтения Эта статья Википедии Кажется, что вы можете сделать это на Vista и Win7 с символическими ссылками. Есть также ссылка на это расширение оболочки что, кажется, охватывает все, что вы можете сделать с этими специальными функциями NTFS. Возможно, с этим вы можете проверить, достижим ли ваша цель, а затем, возможно, проверьте MSDN на желаемую функцию Win32 API.

пытаться:

using System.IO;

string[] filePathsC = Directory.GetFiles(@"c:\");
string[] filePathsD = Directory.GetFiles(@"d:\");

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

РЕДАКТИРОВАТЬ: Читая комментарии, которые я знаю, что я ответил, прежде чем я узнал, что такое жесткая ссылка. Теперь я понимаю, что этот ответ не помогает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top