1. 程式人生 > 其它 >c#獲取檔案或資料夾id

c#獲取檔案或資料夾id

檔案(夾)比較受諸多因素可能出現錯漏,比如大小寫,分隔符,還有父路徑,短路徑等影響,單純的通過字串比較出錯概率很大,本文但要的方法是獲取檔案或資料夾的id,再來比較id判斷提供的路徑是否指向同一物件,程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.IO;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Demo { class Program { const uint FSCTL_GET_OBJECT_ID = 0x0009009c; 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, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, [Out] IntPtr lpOutBuffer, int nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped ); [DllImport("kernel32.dll", SetLastError = true)] public static extern SafeFileHandle CreateFile( String fileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, IntPtr securityAttrs_MustBeZero, System.IO.FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile_MustBeZero ); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool GetFileInformationByHandle( IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); public static String GetFileId(String path) { using (var fs = File.Open( path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite) ) { BY_HANDLE_FILE_INFORMATION info; GetFileInformationByHandle(fs.Handle, out info); return String.Format( "{0:x}", ((info.FileIndexHigh << 32) | info.FileIndexLow)); } } public static FILE_OBJECTID_BUFFER GetFolderIdBuffer(String path) { using (var hFile = CreateFile( path, GENERIC_READ, FileShare.Read, IntPtr.Zero, (FileMode)OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero )) { if (null == hFile || hFile.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); var buffer = default(FILE_OBJECTID_BUFFER); var nOutBufferSize = Marshal.SizeOf(buffer); var lpOutBuffer = Marshal.AllocHGlobal(nOutBufferSize); var lpBytesReturned = default(uint); var result = DeviceIoControl( hFile, FSCTL_GET_OBJECT_ID, IntPtr.Zero, 0, lpOutBuffer, nOutBufferSize, ref lpBytesReturned, IntPtr.Zero ); if (!result) throw new Win32Exception(Marshal.GetLastWin32Error()); var type = typeof(FILE_OBJECTID_BUFFER); buffer = (FILE_OBJECTID_BUFFER) Marshal.PtrToStructure(lpOutBuffer, type); Marshal.FreeHGlobal(lpOutBuffer); return buffer; } } static void Main(string[] args) { var fileid1 = GetFileId(@"C:\Users\a\Desktop\abc.png"); var fileid2 = GetFileId(@"C:\Users\a\Desktop\ABC.png"); var folderid1 = GetFolderIdBuffer(@"C:\Users\a\Desktop\").ObjectId.Reverse() .Select(x => x.ToString("x2")).Aggregate(String.Concat); var folderid2 = GetFolderIdBuffer(@"c:\users\a\..\a\desktop").ObjectId.Reverse() .Select(x => x.ToString("x2")).Aggregate(String.Concat); } } }