1

可能重复:
Windows 中的唯一文件标识符

我需要检索计算机上某些文件的唯一标识符,并且只遇到了 Win32 GetFileInformationByHandle 函数。我怎样才能做到这一点。网络框架?

更新:如果文件被移动、更新、重命名等,我需要一个不会改变的持久 id。

Update2:如何使用文件夹完成相同的操作?

4

3 回答 3

2

这是我从这个答案中复制的Ashley Henderson的一些代码。它意味着两种方法都返回相同的唯一标识符。

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;   
       }
  }
于 2012-04-12T18:44:46.383 回答
1

我假设文件格式不受您的控制(否则,生成 UUID 并将其存储在那里)。

文件对象 ID

NTFS 在文件级别支持对象 ID,请参阅FSCTL_CREATE_OR_GET_OBJECT_ID。我没有使用它们来推荐它们,但这似乎是一个很有前途的探索。

与备用数据流(如下)一样,当复制到非 NTFS 介质(“普通”记忆棒、CD、DVD、闪存卡,甚至可能是一些 USB 磁盘......)时,它们可能会丢失。此外,某些应用程序在保存时重新创建文件时可能会出错。

分布式链接跟踪服务

分布式链接跟踪服务使用文件对象 ID 来跟踪文件链接,并在文件移动时修复它们。

AFAIK 分布式链接跟踪服务需要服务器的域控制器。同样,我没有这方面的实际经验。

在 NTFS 上,您还可以创建 UUID 并将其存储在备用数据流中

注意事项:

  • 仅在 NTFS 上可用,不会在其他文件系统上“存活”
  • 一份白皮书“NTFS 的未来”曾考虑杀死它们,但我认为还有一些其他功能可以帮助您(不幸的是,我没能挖掘出来)
  • 我不想为成千上万个来源和目的未知的文件创建它。尽管它们“只是在文件系统级别上工作”,但某些应用程序可能会搞砸。

某些文档格式(例如 Office)允许自定义文档属性

这显然是有限的,但类似的机制也可以搭载到其他文件类型上。(例如,许多图像格式允许添加/重写应该被读者忽略的“自定义”块)

FileFromID 与 IDFromFile

除 DLTS 之外的所有解决方案都只允许IDFromFile查找,即查找已移动(或已删除)的文件需要搜索所有可能的驱动器。

对于 DLTS,如果没有“直接 API”方式,您可以将启用 DLTS 的快捷方式存储在特定于应用程序的文件夹中,并且~~希望~~希望服务在文件移动时修复快捷方式。

于 2012-04-12T19:18:10.003 回答
-1

You can get the MD5 hash for the files, take this example:

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();
}

this will return a unique identifier for each file.

于 2012-04-12T18:35:24.940 回答