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



        }
    }
}

 

posted on 2022-04-06 16:49  空明流光  阅读(475)  评论(0编辑  收藏  举报

导航