首页

C# 快速搜索磁盘文件

c#

2020-9-10

读取USN Journal,快速搜索文件,程序已设置管理员权限运行。

管理员权限方法自行百度。适用于NTFS磁盘格式,不适用FAT32格式。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;

public class MFTScanner
{
    private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    private const uint GENERIC_READ = 0x80000000;
    private const int FILE_SHARE_READ = 0x1;
    private const int FILE_SHARE_WRITE = 0x2;
    private const int OPEN_EXISTING = 3;
    private const int FILE_READ_ATTRIBUTES = 0x80;
    private const int FILE_NAME_IINFORMATION = 9;
    private const int FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
    private const int FILE_OPEN_FOR_BACKUP_INTENT = 0x4000;
    private const int FILE_OPEN_BY_FILE_ID = 0x2000;
    private const int FILE_OPEN = 0x1;
    private const int OBJ_CASE_INSENSITIVE = 0x40;
    private const int FSCTL_ENUM_USN_DATA = 0x900b3;

    [StructLayout(LayoutKind.Sequential)]
    private struct MFT_ENUM_DATA
    {
        public long StartFileReferenceNumber;
        public long LowUsn;
        public long HighUsn;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct USN_RECORD
    {
        public int RecordLength;
        public short MajorVersion;
        public short MinorVersion;
        public long FileReferenceNumber;
        public long ParentFileReferenceNumber;
        public long Usn;
        public long TimeStamp;
        public int Reason;
        public int SourceInfo;
        public int SecurityId;
        public FileAttributes FileAttributes;
        public short FileNameLength;
        public short FileNameOffset;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct IO_STATUS_BLOCK
    {
        public int Status;
        public int Information;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct UNICODE_STRING
    {
        public short Length;
        public short MaximumLength;
        public IntPtr Buffer;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct OBJECT_ATTRIBUTES
    {
        public int Length;
        public IntPtr RootDirectory;
        public IntPtr ObjectName;
        public int Attributes;
        public int SecurityDescriptor;
        public int SecurityQualityOfService;
    }

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, ref MFT_ENUM_DATA lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, ref int lpBytesReturned, IntPtr lpOverlapped);

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern Int32 CloseHandle(IntPtr lpObject);

    [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int NtCreateFile(ref IntPtr FileHandle, int DesiredAccess, ref OBJECT_ATTRIBUTES ObjectAttributes, ref IO_STATUS_BLOCK IoStatusBlock, int AllocationSize, int FileAttribs, int SharedAccess, int CreationDisposition, int CreateOptions, int EaBuffer,
    int EaLength);

    [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern int NtQueryInformationFile(IntPtr FileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr FileInformation, int Length, int FileInformationClass);

    private IntPtr m_hCJ;
    private IntPtr m_Buffer;
    private int m_BufferSize;

    private string m_DriveLetter;

    private class FSNode
    {
        public long FRN;
        public long ParentFRN;
        public string FileName;

        public bool IsFile;
        public FSNode(long lFRN, long lParentFSN, string sFileName, bool bIsFile)
        {
            FRN = lFRN;
            ParentFRN = lParentFSN;
            FileName = sFileName;
            IsFile = bIsFile;
        }
    }

    private IntPtr OpenVolume(string szDriveLetter)
    {
        m_DriveLetter = szDriveLetter;
        IntPtr hCJ = CreateFile(@"\\.\"   szDriveLetter, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
        return hCJ;
    }


    private void Cleanup()
    {
        if (m_hCJ != IntPtr.Zero)
        {
            CloseHandle(m_hCJ);
            m_hCJ = INVALID_HANDLE_VALUE;
        }

        if (m_Buffer != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(m_Buffer);
            m_Buffer = IntPtr.Zero;
        }
    }


    public IEnumerable<string> EnumerateFiles(string szDriveLetter)
    {
        try
        {
            var usnRecord = default(USN_RECORD);
            var mft = default(MFT_ENUM_DATA);
            var dwRetBytes = 0;
            var cb = 0;
            var dicFRNLookup = new Dictionary<long, FSNode>();
            var bIsFile = false;

            if (m_Buffer.ToInt32() != 0)
            {
                throw new Exception("invalid buffer");
            }

            m_BufferSize = 65536;
            m_Buffer = Marshal.AllocHGlobal(m_BufferSize);
            szDriveLetter = szDriveLetter.TrimEnd('\\');
            m_hCJ = OpenVolume(szDriveLetter);

            if (m_hCJ == INVALID_HANDLE_VALUE)
            {
                string errorMsg = "Couldn't open handle to the volume.";
                if (!IsAdministrator())
                    errorMsg  = "Current user is not administrator";

                throw new Exception(errorMsg);
            }

            mft.StartFileReferenceNumber = 0;
            mft.LowUsn = 0;
            mft.HighUsn = long.MaxValue;

            do
            {
                if (DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, ref mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, ref dwRetBytes, IntPtr.Zero))
                {
                    cb = dwRetBytes;
                    IntPtr pUsnRecord = new IntPtr(m_Buffer.ToInt32()   8);

                    while ((dwRetBytes > 8))
                    {
                        usnRecord = (USN_RECORD)Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType());
                        string FileName = Marshal.PtrToStringUni(new IntPtr(pUsnRecord.ToInt32()   usnRecord.FileNameOffset), usnRecord.FileNameLength / 2);
                        bIsFile = !usnRecord.FileAttributes.HasFlag(FileAttributes.Directory);
                        dicFRNLookup.Add(usnRecord.FileReferenceNumber, new FSNode(usnRecord.FileReferenceNumber, usnRecord.ParentFileReferenceNumber, FileName, bIsFile));
                        pUsnRecord = new IntPtr(pUsnRecord.ToInt32()   usnRecord.RecordLength);
                        dwRetBytes -= usnRecord.RecordLength;
                    }
                    mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0);
                }
                else
                {
                    break; 
                }

            } while (!(cb <= 8));

            foreach (FSNode oFSNode in dicFRNLookup.Values.Where(o => o.IsFile))
            {
                string sFullPath = oFSNode.FileName;
                FSNode oParentFSNode = oFSNode;

                while (dicFRNLookup.TryGetValue(oParentFSNode.ParentFRN, out oParentFSNode))
                {
                    sFullPath = string.Concat(oParentFSNode.FileName, @"\", sFullPath);
                }
                sFullPath = string.Concat(szDriveLetter, @"\", sFullPath);

                yield return sFullPath;
            }
        }
        finally
        {
            Cleanup();
        }
    }

    public static bool IsAdministrator()
    {
        WindowsIdentity identity = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}

资源下载此资源下载价格为3D币(VIP免费),请先
资源文件列表
FF1/.vs/FF1/v16/.suo , 39936
FF1/.vs/FF1/v16/Server/sqlite3/db.lock , 0
FF1/.vs/FF1/v16/Server/sqlite3/storage.ide , 610304
FF1/FF1/App.config , 189
FF1/FF1/bin/Debug/FF1.exe , 18944
FF1/FF1/bin/Debug/FF1.exe.config , 189
FF1/FF1/bin/Debug/FF1.pdb , 42496
FF1/FF1/DriveInfoExtension.cs , 343
FF1/FF1/FF1.csproj , 4060
FF1/FF1/Form1.cs , 690
FF1/FF1/Form1.Designer.cs , 3137
FF1/FF1/Form1.resx , 5817
FF1/FF1/MFTScanner.cs , 8229
FF1/FF1/obj/Debug/DesignTimeResolveAssemblyReferences.cache , 823
FF1/FF1/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache , 7205
FF1/FF1/obj/Debug/FF1.csproj.FileListAbsolute.txt , 336
FF1/FF1/obj/Debug/FF1.csproj.GenerateResource.cache , 1012
FF1/FF1/obj/Debug/FF1.exe , 18944
FF1/FF1/obj/Debug/FF1.Form1.resources , 180
FF1/FF1/obj/Debug/FF1.pdb , 42496
FF1/FF1/obj/Debug/FF1.Properties.Resources.resources , 180
FF1/FF1/Program.cs , 515
FF1/FF1/Properties/app.manifest , 3301
FF1/FF1/Properties/AssemblyInfo.cs , 1298
FF1/FF1/Properties/Resources.Designer.cs , 2819
FF1/FF1/Properties/Resources.resx , 5612
FF1/FF1/Properties/Settings.Designer.cs , 1090
FF1/FF1/Properties/Settings.settings , 249
FF1/FF1.sln , 1115
没有账号? 忘记密码?

社交账号快速登录