Уникальный идентификатор файла
Возможный дубликат:
Уникальный идентификатор файла в windows
Мне нужно получить уникальный идентификатор для определенных файлов на компьютере, и я натолкнулся только на функцию Win32 GetFileInformationByHandle. Как я могу сделать это с. NET Framework?
Обновление: мне нужен постоянный идентификатор, который не изменится, если файл будет перемещен, обновлен, переименован и т. Д.
Обновление 2: Как это можно сделать с папками?
3 ответа
Вот код Ash я скопировал из этого ответа. Это подразумевает два подхода, которые оба возвращают один и тот же уникальный идентификатор.
public class WinAPI
{
[DllImport("ntdll.dll", SetLastError = true)]
public static extern IntPtr NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr pInfoBlock, uint length, FILE_INFORMATION_CLASS fileInformation);
public struct IO_STATUS_BLOCK
{
uint status;
ulong information;
}
public struct _FILE_INTERNAL_INFORMATION {
public ulong IndexNumber;
}
// Abbreviated, there are more values than shown
public enum FILE_INFORMATION_CLASS
{
FileDirectoryInformation = 1, // 1
FileFullDirectoryInformation, // 2
FileBothDirectoryInformation, // 3
FileBasicInformation, // 4
FileStandardInformation, // 5
FileInternalInformation // 6
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation);
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;
}
}
public class Test
{
public ulong ApproachA()
{
WinAPI.IO_STATUS_BLOCK iostatus=new WinAPI.IO_STATUS_BLOCK();
WinAPI._FILE_INTERNAL_INFORMATION objectIDInfo = new WinAPI._FILE_INTERNAL_INFORMATION();
int structSize = Marshal.SizeOf(objectIDInfo);
FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
IntPtr res=WinAPI.NtQueryInformationFile(fs.Handle, ref iostatus, memPtr, (uint)structSize, WinAPI.FILE_INFORMATION_CLASS.FileInternalInformation);
objectIDInfo = (WinAPI._FILE_INTERNAL_INFORMATION)Marshal.PtrToStructure(memPtr, typeof(WinAPI._FILE_INTERNAL_INFORMATION));
fs.Close();
Marshal.FreeHGlobal(memPtr);
return objectIDInfo.IndexNumber;
}
public ulong ApproachB()
{
WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo=new WinAPI.BY_HANDLE_FILE_INFORMATION();
FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt");
FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);
fs.Close();
ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;
return fileIndex;
}
}
Я предполагаю, что формат файла не находится под вашим контролем (в противном случае создайте UUID и сохраните его там).
Идентификаторы файловых объектов
NTFS поддерживает идентификаторы объектов на уровне файлов, см. FSCTL_CREATE_OR_GET_OBJECT_ID. Я не использовал их, чтобы иметь возможность рекомендовать их, но это перспективная вещь для изучения.
Как и в случае альтернативных потоков данных (ниже), они могут потеряться при копировании на не-NTFS-носитель ("обычные" карты памяти, CD, DVD, флэш-карты, возможно, даже некоторые USB-диски. ...). Кроме того, некоторые приложения могут запутаться, когда они воссоздают файл при сохранении.
Служба отслеживания распределенных ссылок
Служба отслеживания распределенных ссылок использует идентификаторы файловых объектов для отслеживания ссылок на файлы и их восстановления при перемещении файла.
Для службы отслеживания распределенных ссылок AFAIK необходим контроллер домена для сервера. Опять же, у меня нет практического опыта с этим.
В NTFS вы также можете создавать и хранить UUID в альтернативном потоке данных.
Предостережения:
- Доступно только в NTFS, не "выживет" в других файловых системах
- Один документ "Будущее NTFS" рассматривал возможность их убийства, но мне кажется, что есть и другие функции, которые могут вам помочь (к сожалению, мне не удалось это выяснить)
- Я не хотел бы создавать это для тысяч файлов неизвестного происхождения и назначения. Хотя они "просто работают" на уровне файловой системы, некоторые приложения могут запутаться.
Некоторые форматы документов, такие как Office, позволяют настраивать свойства документа.
Это, очевидно, ограничено, но аналогичные механизмы можно использовать и для других типов файлов. (например, многие форматы изображений позволяют добавлять / переписывать "пользовательские" фрагменты, которые читатели должны игнорировать)
FileFromID против IDFromFile
Все решения, кроме DLTS, разрешают только IDFromFile
поиск, то есть поиск файла, который был перемещен (или был удален), требует поиска всех потенциальных дисков.
Для DLTS, если не существует способа "прямого API", вы можете сохранить ярлык с поддержкой DLTS в папке, специфичной для приложения, и ~~ надеяться, что ~~ ожидает, что служба исправит ярлык при перемещении файла.
Вы можете получить хеш MD5 для файлов, возьмите этот пример:
string GetMD5HashFromFile(string fileName)
{
FileStream file = new FileStream(fileName, FileMode.Open);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
это вернет уникальный идентификатор для каждого файла.