public static void FillPath(string volume, MyEverythingRecord record, MyEverythingDB db) { if (record == null) return; var fdSource = db.GetFolderSource(volume); string fullpath = record.Name; FindRecordPath(record, ref fullpath, fdSource); record.FullPath = fullpath; }
public void Monitor(List<string> volumes, MyEverythingDB db) { foreach (var volume in volumes) { if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string."); if (!db.ContainsVolume(volume)) throw new InvalidOperationException(string.Format("Volume {0} must be scaned first.")); Thread th = new Thread(new ParameterizedThreadStart(MonitorThread)); th.Start(new Dictionary<string, object> { { "Volume", volume }, { "MyEverythingDB", db } }); } }
private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { MyEverythingRecord record = MyEverythingRecord.ParseUSN(usn); string fullpath = record.Name; db.FindRecordPath(record, ref fullpath, db.GetFolderSource(volume)); record.FullPath = fullpath; db.AddRecord(volume, record, usn.IsFolder ? MyEverythingRecordType.Folder : MyEverythingRecordType.File); Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath)); if (RecordAddedEvent != null) RecordAddedEvent(record); }
public static void FillPath(string volume, MyEverythingRecord record, MyEverythingDB db) { if (record == null) { return; } var fdSource = db.GetFolderSource(volume); string fullpath = record.Name; FindRecordPath(record, ref fullpath, fdSource); record.FullPath = fullpath; }
private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { var cached = db.FindByFrn(volume, usn.FRN); if (cached == null) { return; } else { var isdelete = db.DeleteRecord(volume, usn.FRN); Debug.WriteLine(string.Format(">>>> File {0} deleted {1}.", cached.FullPath, isdelete ? "successful" : "fail")); if (RecordDeletedEvent != null) RecordDeletedEvent(cached); } }
private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { MyEverythingRecord record = MyEverythingRecord.ParseUSN(usn); string fullpath = record.Name; db.FindRecordPath(record, ref fullpath, db.GetFolderSource(volume)); record.FullPath = fullpath; db.AddRecord(volume, record, usn.IsFolder ? MyEverythingRecordType.Folder : MyEverythingRecordType.File); Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath)); if (RecordAddedEvent != null) { RecordAddedEvent(record); } }
public void Monitor(List <string> volumes, MyEverythingDB db) { foreach (var volume in volumes) { if (string.IsNullOrEmpty(volume)) { throw new InvalidOperationException("Volume cant't be null or empty string."); } if (!db.ContainsVolume(volume)) { throw new InvalidOperationException(string.Format("Volume {0} must be scaned first.")); } Thread th = new Thread(new ParameterizedThreadStart(MonitorThread)); th.Start(new Dictionary <string, object> { { "Volume", volume }, { "MyEverythingDB", db } }); } }
private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { var cached = db.FindByFrn(volume, usn.FRN); if (cached == null) { return; } else { var isdelete = db.DeleteRecord(volume, usn.FRN); Debug.WriteLine(string.Format(">>>> File {0} deleted {1}.", cached.FullPath, isdelete ? "successful" : "fail")); if (RecordDeletedEvent != null) { RecordDeletedEvent(cached); } } }
private void MonitorThread(object param) { MyEverythingDB db = (param as Dictionary <string, object>)["MyEverythingDB"] as MyEverythingDB; string volume = (param as Dictionary <string, object>)["Volume"] as string; IntPtr pbuffer = Marshal.AllocHGlobal(0x1000); // 构建输出参数 PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF); // 对所有类型的reason都监听 UInt32 cbRead; // 用来存储实际输出的字节数 IntPtr prujd; // 指向输入参数结构体的指针 while (true) { // 构建输入参数的指针 prujd = Marshal.AllocHGlobal(Marshal.SizeOf(rujd)); PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd)); Marshal.StructureToPtr(rujd, prujd, true); Debug.WriteLine(string.Format("\nMoniting on {0}......", volume)); IntPtr pVolume = MyEverything.GetVolumeJournalHandle(volume); bool fok = PInvokeWin32.DeviceIoControl(pVolume, PInvokeWin32.FSCTL_READ_USN_JOURNAL, prujd, Marshal.SizeOf(typeof(PInvokeWin32.READ_USN_JOURNAL_DATA)), pbuffer, 0x1000, out cbRead, IntPtr.Zero); IntPtr pRealData = new IntPtr(pbuffer.ToInt32() + Marshal.SizeOf(typeof(Int64))); // 返回的内存块头上的8个字节是一个usn_id, 从第9个字节开始才是record. uint offset = 0; if (fok) { while (offset + Marshal.SizeOf(typeof(Int64)) < cbRead) // record可能有多个! { PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(new IntPtr(pRealData.ToInt32() + (int)offset)); ProcessUSN(usn, volume, db); offset += usn.RecordLength; } } Marshal.FreeHGlobal(prujd); rujd.StartUsn = Marshal.ReadInt64(pbuffer); // 返回的内存块头上的8个字节就是用来在进行下一次查询的 } }
private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { var dbCached = db.FindByFrn(volume, usn.FRN); Debug.WriteLine(string.Format("------USN[frn={0}]------", usn.FRN)); Debug.WriteLine(string.Format("FileName={0}, Reason={1}", usn.FileName, Reason.ReasonPrettyFormat(usn.Reason))); Debug.WriteLine(string.Format("FileName[Cached]={0}", dbCached == null ? "NoCache": dbCached.FullPath)); Debug.WriteLine("--------------------------------------"); if (Util.MaskEqual(usn.Reason, Reason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"])) { ProcessRenameNewName(usn, volume, db); } if ((usn.Reason & Reason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0) { ProcessFileCreate(usn, volume, db); } if (Util.MaskEqual(usn.Reason, Reason.USN_REASONS["USN_REASON_FILE_DELETE"])) { ProcessFileDelete(usn, volume, db); } }
static void Main(string[] args) { Console.Write("Volumes for Scan (eg: C: D: E:): "); List <string> volumes = Console.ReadLine().ToUpper().Split(new char[] { ' ' }).ToList(); MyEverythingDB db = new MyEverythingDB(); // ----------------遍历 mft,找到指定 volume 上的所有文件和文件夹---------------- Console.WriteLine("Note: If this is your first time run, it will take some time to open the NTFS Journal System."); var enumFilesTimeStart = DateTime.Now; foreach (string volume in volumes) { List <MyEverythingRecord> files; List <MyEverythingRecord> folders; Console.WriteLine("Scanning {0}...", volume); EnumerateVolume(volume, out files, out folders); db.AddRecord(volume, files, MyEverythingRecordType.File); db.AddRecord(volume, folders, MyEverythingRecordType.Folder); } Console.WriteLine("{0}s file and {1} folder indexed, {2}ms has spent.", db.FileCount, db.FolderCount, DateTime.Now.Subtract(enumFilesTimeStart).TotalMilliseconds); // ----------------------------------------------------------------------------- // ---------------------------命令模式------------------------------ Console.WriteLine("\nMyEverything version 0.0.1"); Console.WriteLine("Type ? for help."); while (true) { Console.Write("MyEverything> "); string[] cmd = Console.ReadLine().Split(' '); long fileFoundCnt; long folderFoundCnt; List <MyEverythingRecord> found; switch (cmd[0].ToLower()) { case "s": if (!string.IsNullOrEmpty(cmd[1])) { var searchtimestart = DateTime.Now; found = db.FindByName(cmd[1], out fileFoundCnt, out folderFoundCnt); found.ForEach(x => FillPath(x.VolumeName, x, db)); var searchtimeend = DateTime.Now; if (cmd.Length == 3 && !string.IsNullOrEmpty(cmd[2])) { using (StreamWriter sw = new StreamWriter(cmd[2], false)) { found.ForEach(x => sw.WriteLine(string.IsNullOrEmpty(x.FullPath) ? x.Name : x.FullPath)); } Console.WriteLine("{0} has written.", cmd[2]); } else { found.ForEach(x => Console.WriteLine(string.IsNullOrEmpty(x.FullPath) ? x.Name : x.FullPath)); } Console.WriteLine("{0}s file and {1}s folder matched, {2}ms has spent.", fileFoundCnt, folderFoundCnt, searchtimeend.Subtract(searchtimestart).TotalMilliseconds); } break; case "?": Console.WriteLine("s filename [logfile]\tSearch files and folders, \n\t\t\tif logfile specified, the result \n\t\t\twill be written to the logfile, \n\t\t\teg: s .txt"); Console.WriteLine("mo volume [debug]\tMonitor the volume, eg: mo E: debug\n\t\t\tIf debug param is specified, some debug msg\n\t\t\twill be print to screen.\n\t\t\tNote: multiple volume monitor is not stable now."); Console.WriteLine("x\t\t\tExit this app."); break; case "x": Environment.Exit(0); break; case "mo": bool pridebug = (cmd.Length == 3) && (cmd[2] == "debug"); VolumeMonitor monitor = new VolumeMonitor(); monitor.RecordAddedEvent += delegate(MyEverythingRecord record) { if (pridebug) { Console.WriteLine(">>>> New file {0} added.", record.FullPath); } }; monitor.RecordDeletedEvent += delegate(MyEverythingRecord record) { if (pridebug) { Console.WriteLine(">>>> File {0} deleted.", record.FullPath); } }; monitor.RecordRenameEvent += delegate(MyEverythingRecord oldRecord, MyEverythingRecord newRecord) { if (pridebug) { Console.WriteLine(">>>> File {0} renamed to {1}.", oldRecord.FullPath, newRecord.FullPath); } }; monitor.Monitor(cmd[1].ToUpper().Split(' ').ToList(), db); Console.WriteLine("Moniting on {0}......", cmd[1].ToUpper()); break; } } }
private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { // frn 没有改变 // newname = usn.FileName // 根据usn.FRN可以从db中获取oldname // db.update... MyEverythingRecord newRecord = MyEverythingRecord.ParseUSN(usn); string fullpath = newRecord.Name; db.FindRecordPath(newRecord, ref fullpath, db.GetFolderSource(volume)); newRecord.FullPath = fullpath; var oldRecord = db.FindByFrn(volume, usn.FRN); string newname = newRecord.FullPath; Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newname)); db.UpdateRecord(volume, newRecord, usn.IsFolder ? MyEverythingRecordType.Folder : MyEverythingRecordType.File); if (RecordRenameEvent != null) { RecordRenameEvent(oldRecord, newRecord); } if (newname.Contains("$RECYCLE.BIN")) { Debug.WriteLine(string.Format(">>>> Means {0} moved to recycle.", oldRecord.FullPath)); } }
static void Main(string[] args) { Console.Write("Volumes for Scan (eg: C: D: E:): "); List<string> volumes = Console.ReadLine().ToUpper().Split(new char[] {' '}).ToList(); MyEverythingDB db = new MyEverythingDB(); // ----------------遍历 mft,找到指定 volume 上的所有文件和文件夹---------------- Console.WriteLine("Note: If this is your first time run, it will take some time to open the NTFS Journal System."); var enumFilesTimeStart = DateTime.Now; foreach (string volume in volumes) { List<MyEverythingRecord> files; List<MyEverythingRecord> folders; Console.WriteLine("Scanning {0}...", volume); EnumerateVolume(volume, out files, out folders); db.AddRecord(volume, files, MyEverythingRecordType.File); db.AddRecord(volume, folders, MyEverythingRecordType.Folder); } Console.WriteLine("{0}s file and {1} folder indexed, {2}ms has spent.", db.FileCount, db.FolderCount, DateTime.Now.Subtract(enumFilesTimeStart).TotalMilliseconds); // ----------------------------------------------------------------------------- // ---------------------------命令模式------------------------------ Console.WriteLine("\nMyEverything version 0.0.1"); Console.WriteLine("Type ? for help."); while (true) { Console.Write("MyEverything> "); string[] cmd = Console.ReadLine().Split(' '); long fileFoundCnt; long folderFoundCnt; List<MyEverythingRecord> found; switch (cmd[0].ToLower()) { case "s": if (!string.IsNullOrEmpty(cmd[1])) { var searchtimestart = DateTime.Now; found = db.FindByName(cmd[1], out fileFoundCnt, out folderFoundCnt); found.ForEach(x => FillPath(x.VolumeName, x, db)); var searchtimeend = DateTime.Now; if (cmd.Length == 3 && !string.IsNullOrEmpty(cmd[2])) { using (StreamWriter sw = new StreamWriter(cmd[2], false)) { found.ForEach(x => sw.WriteLine(string.IsNullOrEmpty(x.FullPath) ? x.Name : x.FullPath)); } Console.WriteLine("{0} has written.", cmd[2]); } else { found.ForEach(x => Console.WriteLine(string.IsNullOrEmpty(x.FullPath) ? x.Name : x.FullPath)); } Console.WriteLine("{0}s file and {1}s folder matched, {2}ms has spent.", fileFoundCnt, folderFoundCnt, searchtimeend.Subtract(searchtimestart).TotalMilliseconds); } break; case "?": Console.WriteLine("s filename [logfile]\tSearch files and folders, \n\t\t\tif logfile specified, the result \n\t\t\twill be written to the logfile, \n\t\t\teg: s .txt"); Console.WriteLine("mo volume [debug]\tMonitor the volume, eg: mo E: debug\n\t\t\tIf debug param is specified, some debug msg\n\t\t\twill be print to screen.\n\t\t\tNote: multiple volume monitor is not stable now."); Console.WriteLine("x\t\t\tExit this app."); break; case "x": Environment.Exit(0); break; case "mo": bool pridebug = (cmd.Length == 3) && (cmd[2] == "debug"); VolumeMonitor monitor = new VolumeMonitor(); monitor.RecordAddedEvent += delegate(MyEverythingRecord record) { if (pridebug) Console.WriteLine(">>>> New file {0} added.", record.FullPath); }; monitor.RecordDeletedEvent += delegate(MyEverythingRecord record) { if (pridebug) Console.WriteLine(">>>> File {0} deleted.", record.FullPath); }; monitor.RecordRenameEvent += delegate(MyEverythingRecord oldRecord, MyEverythingRecord newRecord) { if (pridebug) Console.WriteLine(">>>> File {0} renamed to {1}.", oldRecord.FullPath, newRecord.FullPath); }; monitor.Monitor(cmd[1].ToUpper().Split(' ').ToList(), db); Console.WriteLine("Moniting on {0}......", cmd[1].ToUpper()); break; } } }
private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { // frn 没有改变 // newname = usn.FileName // 根据usn.FRN可以从db中获取oldname // db.update... MyEverythingRecord newRecord = MyEverythingRecord.ParseUSN(usn); string fullpath = newRecord.Name; db.FindRecordPath(newRecord, ref fullpath, db.GetFolderSource(volume)); newRecord.FullPath = fullpath; var oldRecord = db.FindByFrn(volume, usn.FRN); string newname = newRecord.FullPath; Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newname)); db.UpdateRecord(volume, newRecord, usn.IsFolder ? MyEverythingRecordType.Folder : MyEverythingRecordType.File); if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord); if (newname.Contains("$RECYCLE.BIN")) { Debug.WriteLine(string.Format(">>>> Means {0} moved to recycle.", oldRecord.FullPath)); } }
private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MyEverythingDB db) { var dbCached = db.FindByFrn(volume, usn.FRN); Debug.WriteLine(string.Format("------USN[frn={0}]------", usn.FRN)); Debug.WriteLine(string.Format("FileName={0}, Reason={1}", usn.FileName, Reason.ReasonPrettyFormat(usn.Reason))); Debug.WriteLine(string.Format("FileName[Cached]={0}", dbCached == null ? "NoCache": dbCached.FullPath)); Debug.WriteLine("--------------------------------------"); if (Util.MaskEqual(usn.Reason, Reason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"])) ProcessRenameNewName(usn, volume, db); if ((usn.Reason & Reason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0) ProcessFileCreate(usn, volume, db); if (Util.MaskEqual(usn.Reason, Reason.USN_REASONS["USN_REASON_FILE_DELETE"])) ProcessFileDelete(usn, volume, db); }