C# windows中的唯一文件标识符

C# windows中的唯一文件标识符,c#,.net,windows,filesystems,C#,.net,Windows,Filesystems,是否有方法在文件生命周期内唯一标识文件(可能还有目录),而不考虑移动、重命名和内容修改?(Windows 2000及更高版本)。制作文件副本时,应为副本提供自己的唯一标识符 我的应用程序将各种元数据与单个文件相关联。如果文件被修改、重命名或移动,则能够自动检测和更新文件关联将非常有用 FileSystemWatcher可以提供通知这些更改的事件,但是它使用了一个内存缓冲区,如果许多文件系统事件很快发生,则可以很容易地填充(以及事件丢失) 散列是没有用的,因为文件的内容可以更改,因此散列也会更改

是否有方法在文件生命周期内唯一标识文件(可能还有目录),而不考虑移动、重命名和内容修改?(Windows 2000及更高版本)。制作文件副本时,应为副本提供自己的唯一标识符

我的应用程序将各种元数据与单个文件相关联。如果文件被修改、重命名或移动,则能够自动检测和更新文件关联将非常有用

FileSystemWatcher可以提供通知这些更改的事件,但是它使用了一个内存缓冲区,如果许多文件系统事件很快发生,则可以很容易地填充(以及事件丢失)

散列是没有用的,因为文件的内容可以更改,因此散列也会更改

我曾考虑过使用文件创建日期,但是在某些情况下,该日期不是唯一的(例如,当复制多个文件时)

我还听说NTFS中有一个文件SID(安全ID?),但我不确定这是否符合我的要求

有什么想法吗?

请看这里:。这也很有用:

如果您调用,您将通过\u HANDLE\u file\u INFORMATION.nFileIndexHigh/Low在中获得文件ID。此索引在卷中是唯一的,即使您移动文件(在卷中)或重命名文件,也会保持不变


如果您可以假设使用NTFS,您可能还需要考虑使用备用数据流来存储元数据。

< P>这里是返回唯一文件索引的示例代码。 ApproachA()是我经过一番研究后得出的结论。ApproachB()感谢Mattias和Rubens提供的链接中的信息。给定一个特定的文件,两种方法都返回相同的文件索引(在我的基本测试期间)

MSDN中的一些注意事项:

对文件ID的支持是文件 特定于系统。文件ID不可用 保证随着时间的推移是独一无二的, 因为文件系统可以自由重用 他们在某些情况下,文件的文件ID 文件可以随时间而更改。

在FAT文件系统中,文件ID是 从 包含的目录和字节 目录中的偏移量 文件的条目。一些 碎片整理产品改变了这一点 字节偏移量。(盒子里的窗户 碎片整理不会。)因此,FAT 文件ID可以随时间变化。更名 FAT文件系统中的文件也可以 更改文件ID,但仅当 新文件名比旧文件名长 一个

在NTFS文件系统中,文件保持 相同的文件ID,直到删除为止。 您可以用另一个文件替换一个文件 文件,而不更改文件ID 使用ReplaceFile函数。 但是,文件的文件ID 替换文件,而不是被替换的 文件,保留为的文件ID 生成的文件

上面第一个大胆的评论让我担心。目前尚不清楚该声明是否仅适用于FAT,它似乎与第二个粗体文本相矛盾。我想进一步的测试是唯一确定的方法

[更新:在我的测试中,当文件从一个内部NTFS硬盘驱动器移动到另一个内部NTFS硬盘驱动器时,文件索引/id会发生变化。]

    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;   
       }
  }
公共类WinAPI
{
[DllImport(“ntdll.dll”,SetLastError=true)]
公共静态外部IntPtr NtQueryInformationFile(IntPtr文件句柄、ref IO_STATUS_块IoStatusBlock、IntPtr pInfoBlock、uint长度、文件信息_类文件信息);
公共结构IO_状态_块
{
uint状态;
乌龙信息;
}
公共结构文件内部信息{
公共ulong指数编号;
} 
//缩写后的值比显示的值多
公共枚举文件\u信息\u类
{
FileDirectoryInformation=1,//1
FileFullDirectoryInformation,//2
FileBothDirectoryInformation,//3
FileBasicInformation,//4
文件标准信息,//5
文件内部信息//6
}
[DllImport(“kernel32.dll”,SetLastError=true)]
公共静态外部bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation);
公共结构的句柄文件信息
{
公共uint文件属性;
公共文件时间创建时间;
公共文件时间LastAccessTime;
公共文件时间LastWriteTime;
公共单位卷序号;
公共单元文件大小高;
公共uint文件;
公共uint链接数;
公共uint文件索引高;
公共uint FileIndexLow;
}
}
公开课考试
{
公共乌龙方法()
{
WinAPI.IO_STATUS_BLOCK iostatus=新的WinAPI.IO_STATUS_BLOCK();
WinAPI._FILE_INTERNAL_INFORMATION objectIDInfo=新的WinAPI._FILE_INTERNAL_INFORMATION();
int structSize=Marshal.SizeOf(objectIDInfo);
FileInfo fi=newfileinfo(@“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\u INFORMATION\u CLASS.FileInternalInformation);
objectIDInfo=(WinAPI.\u文件\内部\信息)Marshal.ptr结构(memPtr,typeof(WinAPI.\u文件\内部\信息));
fs.Close();
弗里赫全球元帅(memPtr);
返回objectindinfo.IndexNumber;
}
公共乌龙通道B()
{
WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo=新的WinAPI.BY_HANDLE_FILE_INFORMATION();
FileInfo fi=newfileinfo(@“C:\Temp\testfile.txt”);
FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern SafeFileHandle CreateFile(
            string lpFileName,
            [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
            [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
            IntPtr securityAttributes,
            [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile
        );