C#实现全盘扫描,找到符合要求的文件,并把路径写入到TXT中
admin
2024-03-13 02:20:36

好久没更新文章了,来水一篇。

最近领导安排了个任务,让把服务器上符合要求的文件的路径找出来。windos自带的搜索功能太慢了,everything不想下载,想着自己实现一个,实现完成发现速度也不是很慢。

实现思路。
1.先把电脑中的所有驱动器名称拿到。
2.遍历启动器中的文件。
3.符合要求的文件写入文本。

第一步中查了下资料,C#提供的有个DriveInfo的类,可以获取到所有驱动器相关的信息。

第二步,遍历文件,这个一看就是费脑力的活,自己写估计效率很低,这个直接网上参考了国外大佬实现的类,直接用就行了。遍历速度和everything差不多。

第三步,写入txt。这个就很简单了。不过也是CV。

下面贴出具体实现代码,代码有注释。就不具体解释了。

1.程序入口

using System;
using System.IO;
using System.Linq;namespace 文件扫描器
{class Program{static void Main(string[] args){//全盘扫描DriveInfo[] driveInfo = DriveInfo.GetDrives();foreach (DriveInfo info in driveInfo){var MFTfile = new DriveInfo(info.Name).EnumerateFiles();//获得C盘所有文件路径var FindFiles = MFTfile.Where(x =>Path.GetFileName(x) == "大写.config" || Path.GetFileName(x) == "小写.config");//遍历获得的全部文件路径,查找所需的文件foreach (string strpath in FindFiles){WriteText.WriteDocument(strpath);}}Console.WriteLine("执行成功!");Console.Read();}}
}

2.遍历文件的类。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;namespace 文件扫描器
{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;} MFT_ENUM_DATA[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){IntPtr hCJ = default(IntPtr); volume handlem_DriveLetter = szDriveLetter;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){// Close the volume handle.CloseHandle(m_hCJ);m_hCJ = INVALID_HANDLE_VALUE;}if (m_Buffer != IntPtr.Zero){// Free the allocated memoryMarshal.FreeHGlobal(m_Buffer);m_Buffer = IntPtr.Zero;}}public IEnumerable 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();var bIsFile = false;// This shouldn't be called more than once.if (m_Buffer.ToInt32() != 0){throw new Exception("invalid buffer");}// Assign buffer sizem_BufferSize = 65536;//64KB// Allocate a buffer to use for reading records.m_Buffer = Marshal.AllocHGlobal(m_BufferSize);// correct pathszDriveLetter = szDriveLetter.TrimEnd('\\');// Open the volume handlem_hCJ = OpenVolume(szDriveLetter);// Check if the volume handle is valid.if (m_hCJ == INVALID_HANDLE_VALUE){string errorMsg = "Couldn't open handle to the volume.";if (!IsAdministrator())errorMsg += "Current user is not administrator";}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;// Pointer to the first recordIntPtr pUsnRecord = new IntPtr(m_Buffer.ToInt64() + 8);while ((dwRetBytes > 8)){// Copy pointer to USN_RECORD structure.usnRecord = (USN_RECORD)Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType());// The filename within the USN_RECORD.string FileName = Marshal.PtrToStringUni(new IntPtr(pUsnRecord.ToInt64() + usnRecord.FileNameOffset), usnRecord.FileNameLength / 2);bIsFile = !usnRecord.FileAttributes.HasFlag(FileAttributes.Directory);dicFRNLookup.Add(usnRecord.FileReferenceNumber, new FSNode(usnRecord.FileReferenceNumber, usnRecord.ParentFileReferenceNumber, FileName, bIsFile));// Pointer to the next record in the buffer.pUsnRecord = new IntPtr(pUsnRecord.ToInt64() + usnRecord.RecordLength);dwRetBytes -= usnRecord.RecordLength;}// The first 8 bytes is always the start of the next USN.mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0);}else{break; // TODO: might not be correct. Was : Exit Do}} while (!(cb <= 8));// Resolve all paths for Filesforeach (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{ cleanupCleanup();}}public static bool IsAdministrator(){WindowsIdentity identity = WindowsIdentity.GetCurrent();WindowsPrincipal principal = new WindowsPrincipal(identity);return principal.IsInRole(WindowsBuiltInRole.Administrator);}}public static class DriveInfoExtension{public static IEnumerable EnumerateFiles(this DriveInfo drive){return (new MFTScanner()).EnumerateFiles(drive.Name);}}
}

该类需要使用引用using System.Security.Principal;自己Nuget一下。

3.写入txt类。

using System;
using System.Collections.Generic;
using System.Text;namespace 文件扫描器
{class WriteText{public static void WriteDocument(string  strpath) {using (System.IO.StreamWriter file =new System.IO.StreamWriter(@"C:\WriteLines.txt", true)){file.WriteLine(strpath);}}}
}

好了,今天文章已水完~希望大家有收获。

相关内容

热门资讯

过去复制恒大、如今模仿海港?国... (来源:上观新闻)北京国安俱乐部近日举行新任主教练蒙哥马利的就职发布会,这已是第四支聘请 “澳波系”...
开油烟机做饭 记得给厨房留道缝   开着油烟机的厨房内形成负压,轻易地吸进纸巾。  红圈内的上下数值分别为一氧化碳和氧气浓度。本报记...
党建领航 首都教育亮出42张“...   1月12日下午,北京市首批基础教育党建品牌示范推广活动正式启动,首批42个覆盖全市各区、涵盖区级...
中信证券间接子公司发行1亿港元... 中访网数据  中信证券股份有限公司(证券代码:600030)于2026年1月13日发布公告,披露其间...
最新或2023(历届)感恩节专...   【广播稿1】  一、音乐导入:以一首《感恩的心》作为开场音乐。  甲:感恩的心,感谢有你,伴我一...