获取文件夹ID C#
发布时间:2020-12-15 05:39:23 所属栏目:百科 来源:网络整理
导读:我试图在他们的生命周期中跟踪文件和文件夹(他们可能被移动或重命名).我已经完成了搜索,发现 FileSystemWatcher可能是最流行的跟踪文件和文件夹的方式,但是,这对我来说不起作用,因为应用程序可能会或可能不会一直运行.我选择尝试通过ID跟踪文件夹. 我找到了
我试图在他们的生命周期中跟踪文件和文件夹(他们可能被移动或重命名).我已经完成了搜索,发现
FileSystemWatcher可能是最流行的跟踪文件和文件夹的方式,但是,这对我来说不起作用,因为应用程序可能会或可能不会一直运行.我选择尝试通过ID跟踪文件夹.
我找到了一种方法来跟踪从答案到this stack post的ID中的文件.我可以在this answer中基于方法B成功获取文件ID. 在搜索时我发现this stack post说他找到了使用FSCTL_GET_OBJECT_ID的解决方案.我花了很多时间试图弄清楚如何使用这个功能,但我无法绕过它.我基本上没有从C#中调用本机Windows函数的经验. 任何人都可以为我推动正确的方向吗?我觉得我必须遗漏一些明显的东西. 有没有理由C#无法访问文件/文件夹ID?跟踪文件/文件夹是不常见的? 编辑,添加代码: static uint returnVal; //Working example to get File ID public static string GetFileId(string path) { WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION(); FileInfo fi = new FileInfo(path); 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.ToString(); } public static string GetFolderId(string path) { //Get a handle on the given folder IntPtr cFile = WinAPI.CreateFile( path,WinAPI.GENERIC_READ,FileShare.Read,IntPtr.Zero,(FileMode)WinAPI.OPEN_EXISTING,WinAPI.FILE_FLAG_BACKUP_SEMANTICS,IntPtr.Zero); Console.WriteLine(path); Console.WriteLine(cFile); if ((int)cFile != -1) { int cFileSize = Marshal.SizeOf(typeof(IntPtr)); Console.WriteLine("cFile size = {0}",cFileSize); IntPtr cFileBlob = Marshal.AllocHGlobal(cFileSize); uint numBytesRead = 0; WinAPI.DeviceIoControl(cFile,WinAPI.FSCTL_GET_OBJECT_ID,cFileBlob,(uint)cFileSize,ref numBytesRead,IntPtr.Zero); if (returnVal == 0) { Console.WriteLine(Marshal.GetLastWin32Error()); // Returning error 87 here } } //Should be returning the ID from the folder. return String.Empty; } public static void Main(string[] args) { Console.WriteLine(GetFileId(@"C:UsersMattDesktopTestDocument.txt")); Console.WriteLine(GetFolderId(@"C:UsersMattDesktop")); } } class WinAPI { // Win32 constants for accessing files. internal const int GENERIC_READ = unchecked((int)0x80000000); internal const int FILE_FLAG_BACKUP_SEMANTICS = unchecked((int)0x02000000); internal const int OPEN_EXISTING = unchecked((int)3); internal const int FSCTL_GET_OBJECT_ID = 0x0009009c; internal const int FSCTL_CREATE_OR_GET_OBJECT_ID = 0x000900c0; [DllImport("kernel32.dll",SetLastError = true)] public static extern bool DeviceIoControl(IntPtr hDevice,uint dwIoControlCode,IntPtr lpInBuffer,uint nInBufferSize,[Out] IntPtr lpOutBuffer,uint nOutBufferSize,ref uint lpBytesReturned,IntPtr lpOverlapped); [DllImport("kernel32.dll",SetLastError = true)] public static extern bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation); [DllImport("kernel32.dll",SetLastError = true)] public static extern IntPtr CreateFile( String fileName,int dwDesiredAccess,System.IO.FileShare dwShareMode,IntPtr securityAttrs_MustBeZero,System.IO.FileMode dwCreationDisposition,int dwFlagsAndAttributes,IntPtr hTemplateFile_MustBeZero); 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; } } 我从DeviceIoControl返回错误“87”,这是根据MSDN上的帖子无效参数(由于声誉限制,我无法发布更多链接.) 解决方法
似乎你对FileSystemWatcher没有任何问题.那么,对于如何在C#中使用DeviceIoControl,看看这个答案:
Physical disk size not correct (IoCtlDiskGetDriveGeometry) 对于这个问题,它使用以下代码完成: class Program { const uint FSCTL_GET_OBJECT_ID=0x0009009c; public static String GetFileId(String path) { using(var fs=File.Open( path,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite) ) { WinAPI.BY_HANDLE_FILE_INFORMATION info; WinAPI.GetFileInformationByHandle(fs.Handle,out info); return String.Format( "{0:x}",((info.FileIndexHigh<<32)|info.FileIndexLow)); } } public static WinAPI.FILE_OBJECTID_BUFFER GetFolderIdBuffer(String path) { using(var hFile=WinAPI.CreateFile( path,IntPtr.Zero )) { if(null==hFile||hFile.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); var buffer=default(WinAPI.FILE_OBJECTID_BUFFER); var nOutBufferSize=Marshal.SizeOf(buffer); var lpOutBuffer=Marshal.AllocHGlobal(nOutBufferSize); var lpBytesReturned=default(uint); var result= WinAPI.DeviceIoControl( hFile,FSCTL_GET_OBJECT_ID,lpOutBuffer,nOutBufferSize,ref lpBytesReturned,IntPtr.Zero ); if(!result) throw new Win32Exception(Marshal.GetLastWin32Error()); var type=typeof(WinAPI.FILE_OBJECTID_BUFFER); buffer=(WinAPI.FILE_OBJECTID_BUFFER) Marshal.PtrToStructure(lpOutBuffer,type); Marshal.FreeHGlobal(lpOutBuffer); return buffer; } } public static void Main(String[] args) { Console.WriteLine( GetFileId(@"C:UsersMattDesktopTestDocument.txt")); var buffer=GetFolderIdBuffer(@"C:UsersMattDesktop"); var objectId=buffer.ObjectId .Reverse() .Select(x => x.ToString("x2")) .Aggregate(String.Concat); Console.WriteLine("{0}",objectId); } } class WinAPI { internal const int GENERIC_READ=unchecked((int)0x80000000),FILE_FLAG_BACKUP_SEMANTICS=unchecked((int)0x02000000),OPEN_EXISTING=unchecked((int)3); [StructLayout(LayoutKind.Sequential)] public struct FILE_OBJECTID_BUFFER { public struct Union { [MarshalAs(UnmanagedType.ByValArray,SizeConst=16)] public byte[] BirthVolumeId; [MarshalAs(UnmanagedType.ByValArray,SizeConst=16)] public byte[] BirthObjectId; [MarshalAs(UnmanagedType.ByValArray,SizeConst=16)] public byte[] DomainId; } [MarshalAs(UnmanagedType.ByValArray,SizeConst=16)] public byte[] ObjectId; public Union BirthInfo; [MarshalAs(UnmanagedType.ByValArray,SizeConst=48)] public byte[] ExtendedInfo; } [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)] public static extern bool DeviceIoControl( SafeFileHandle hDevice,int nOutBufferSize,IntPtr lpOverlapped ); [DllImport("kernel32.dll",SetLastError=true)] public static extern SafeFileHandle CreateFile( String fileName,IntPtr hTemplateFile_MustBeZero ); [DllImport("kernel32.dll",SetLastError=true)] public static extern bool GetFileInformationByHandle( IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation); } 名称空间需要使用: using Microsoft.Win32.SafeHandles; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |