mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 20:27:36 +02:00
Add search monitor
This commit is contained in:
@@ -15,11 +15,13 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
public class MFTSearcher
|
public class MFTSearcher
|
||||||
{
|
{
|
||||||
private static MFTSearcherCache cache = new MFTSearcherCache();
|
private static MFTSearcherCache cache = new MFTSearcherCache();
|
||||||
|
private static VolumeMonitor monitor = new VolumeMonitor();
|
||||||
|
|
||||||
private static void IndexVolume(string volume)
|
private static void IndexVolume(string volume)
|
||||||
{
|
{
|
||||||
cache.CheckHashTableKey(volume);
|
cache.EnsureVolumeExistInHashTable(volume);
|
||||||
EnumerateVolume(volume,cache.VolumeRecords[volume]);
|
EnumerateVolume(volume, cache.VolumeRecords[volume]);
|
||||||
|
monitor.Monitor(volume,cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void IndexAllVolumes()
|
public static void IndexAllVolumes()
|
||||||
@@ -39,7 +41,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(item)) return new List<MFTSearchRecord>();
|
if (string.IsNullOrEmpty(item)) return new List<MFTSearchRecord>();
|
||||||
|
|
||||||
List<USNRecord> found = cache.FindByName(item,100);
|
List<USNRecord> found = cache.FindByName(item, 100);
|
||||||
found.ForEach(x => FillPath(x.VolumeName, x, cache));
|
found.ForEach(x => FillPath(x.VolumeName, x, cache));
|
||||||
return found.ConvertAll(o => new MFTSearchRecord(o));
|
return found.ConvertAll(o => new MFTSearchRecord(o));
|
||||||
}
|
}
|
||||||
@@ -65,7 +67,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh;
|
UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh;
|
||||||
UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow;
|
UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow;
|
||||||
|
|
||||||
files.Add(indexRoot,new USNRecord
|
files.Add(indexRoot, new USNRecord
|
||||||
{
|
{
|
||||||
FRN = indexRoot,
|
FRN = indexRoot,
|
||||||
Name = volumeName,
|
Name = volumeName,
|
||||||
@@ -94,7 +96,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
IntPtr pVolume = IntPtr.Zero;
|
IntPtr pVolume = IntPtr.Zero;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AddVolumeRootRecord(volumeName,files);
|
AddVolumeRootRecord(volumeName, files);
|
||||||
pVolume = GetVolumeJournalHandle(volumeName);
|
pVolume = GetVolumeJournalHandle(volumeName);
|
||||||
EnableVomuleJournal(pVolume);
|
EnableVomuleJournal(pVolume);
|
||||||
|
|
||||||
@@ -217,7 +219,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
{
|
{
|
||||||
PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord);
|
PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord);
|
||||||
|
|
||||||
files.Add(usn.FRN,new USNRecord
|
files.Add(usn.FRN, new USNRecord
|
||||||
{
|
{
|
||||||
Name = usn.FileName,
|
Name = usn.FileName,
|
||||||
ParentFrn = usn.ParentFRN,
|
ParentFrn = usn.ParentFRN,
|
||||||
|
|||||||
@@ -17,17 +17,20 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
|
|
||||||
public void AddRecord(string volume, List<USNRecord> r)
|
public void AddRecord(string volume, List<USNRecord> r)
|
||||||
{
|
{
|
||||||
CheckHashTableKey(volume);
|
EnsureVolumeExistInHashTable(volume);
|
||||||
r.ForEach(x => VolumeRecords[volume].Add(x.FRN, x));
|
r.ForEach(x => VolumeRecords[volume].Add(x.FRN, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRecord(string volume, USNRecord record)
|
public void AddRecord(string volume, USNRecord record)
|
||||||
{
|
{
|
||||||
CheckHashTableKey(volume);
|
EnsureVolumeExistInHashTable(volume);
|
||||||
VolumeRecords[volume].Add(record.FRN, record);
|
if (!VolumeRecords[volume].ContainsKey(record.FRN))
|
||||||
|
{
|
||||||
|
VolumeRecords[volume].Add(record.FRN, record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckHashTableKey(string volume)
|
public void EnsureVolumeExistInHashTable(string volume)
|
||||||
{
|
{
|
||||||
if (!VolumeRecords.ContainsKey(volume))
|
if (!VolumeRecords.ContainsKey(volume))
|
||||||
VolumeRecords.Add(volume, new Dictionary<ulong, USNRecord>());
|
VolumeRecords.Add(volume, new Dictionary<ulong, USNRecord>());
|
||||||
|
|||||||
@@ -16,12 +16,18 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
{
|
{
|
||||||
foreach (var volume in volumes)
|
foreach (var volume in volumes)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string.");
|
Monitor(volume, db);
|
||||||
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 }, { "MFTSearcherCache", db } });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Monitor(string volume, MFTSearcherCache db)
|
||||||
|
{
|
||||||
|
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."));
|
||||||
|
|
||||||
|
ThreadPool.QueueUserWorkItem(o => MonitorThread(volume, db));
|
||||||
|
}
|
||||||
|
|
||||||
private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason)
|
private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason)
|
||||||
{
|
{
|
||||||
IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume);
|
IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume);
|
||||||
@@ -40,11 +46,9 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
|
|
||||||
return rujd;
|
return rujd;
|
||||||
}
|
}
|
||||||
private void MonitorThread(object param)
|
|
||||||
{
|
|
||||||
|
|
||||||
MFTSearcherCache db = (param as Dictionary<string, object>)["MFTSearcherCache"] as MFTSearcherCache;
|
private void MonitorThread(string volume, MFTSearcherCache db)
|
||||||
string volume = (param as Dictionary<string, object>)["Volume"] as string;
|
{
|
||||||
IntPtr pbuffer = Marshal.AllocHGlobal(0x1000);
|
IntPtr pbuffer = Marshal.AllocHGlobal(0x1000);
|
||||||
PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF);
|
PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF);
|
||||||
UInt32 cbRead;
|
UInt32 cbRead;
|
||||||
@@ -56,7 +60,6 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd));
|
PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd));
|
||||||
Marshal.StructureToPtr(rujd, prujd, true);
|
Marshal.StructureToPtr(rujd, prujd, true);
|
||||||
|
|
||||||
Debug.WriteLine(string.Format("\nMoniting on {0}......", volume));
|
|
||||||
IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume);
|
IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume);
|
||||||
|
|
||||||
bool fok = PInvokeWin32.DeviceIoControl(pVolume,
|
bool fok = PInvokeWin32.DeviceIoControl(pVolume,
|
||||||
@@ -81,15 +84,9 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
rujd.StartUsn = Marshal.ReadInt64(pbuffer);
|
rujd.StartUsn = Marshal.ReadInt64(pbuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
||||||
{
|
{
|
||||||
var dbCached = db.FindByFrn(volume, usn.FRN);
|
|
||||||
MFTSearcher.FillPath(volume, dbCached, db);
|
|
||||||
Debug.WriteLine(string.Format("------USN[frn={0}]------", usn.FRN));
|
|
||||||
Debug.WriteLine(string.Format("FileName={0}, USNChangeReason={1}", usn.FileName, USNChangeReason.ReasonPrettyFormat(usn.Reason)));
|
|
||||||
Debug.WriteLine(string.Format("FileName[Cached]={0}", dbCached == null ? "NoCache" : dbCached.FullPath));
|
|
||||||
Debug.WriteLine("--------------------------------------");
|
|
||||||
|
|
||||||
if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"]))
|
if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"]))
|
||||||
ProcessRenameNewName(usn, volume, db);
|
ProcessRenameNewName(usn, volume, db);
|
||||||
if ((usn.Reason & USNChangeReason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0)
|
if ((usn.Reason & USNChangeReason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0)
|
||||||
@@ -97,47 +94,37 @@ namespace Wox.Plugin.FindFile.MFTSearch
|
|||||||
if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_FILE_DELETE"]))
|
if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_FILE_DELETE"]))
|
||||||
ProcessFileDelete(usn, volume, db);
|
ProcessFileDelete(usn, volume, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
||||||
{
|
{
|
||||||
var cached = db.FindByFrn(volume, usn.FRN);
|
var cached = db.FindByFrn(volume, usn.FRN);
|
||||||
if (cached == null)
|
if (cached != null)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
MFTSearcher.FillPath(volume, cached, db);
|
MFTSearcher.FillPath(volume, cached, db);
|
||||||
var deleteok = db.DeleteRecord(volume, usn.FRN);
|
var deleteok = db.DeleteRecord(volume, usn.FRN);
|
||||||
Debug.WriteLine(string.Format(">>>> File {0} deleted {1}.", cached.FullPath, deleteok ? "successful" : "fail"));
|
Debug.WriteLine(string.Format(">>>> DeleteFIle {0} {1}.", cached.FullPath, deleteok ? "successful" : "fail"));
|
||||||
if (RecordDeletedEvent != null)
|
if (RecordDeletedEvent != null)
|
||||||
RecordDeletedEvent(cached);
|
RecordDeletedEvent(cached);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
||||||
{
|
{
|
||||||
USNRecord newRecord = USNRecord.ParseUSN(volume, usn);
|
USNRecord newRecord = USNRecord.ParseUSN(volume, usn);
|
||||||
//string fullpath = newRecord.Name;
|
|
||||||
//db.FindRecordPath(newRecord, ref fullpath, db.GetVolumeRecords(volume));
|
|
||||||
//newRecord.FullPath = fullpath;
|
|
||||||
var oldRecord = db.FindByFrn(volume, usn.FRN);
|
|
||||||
MFTSearcher.FillPath(volume, oldRecord, db);
|
|
||||||
MFTSearcher.FillPath(volume, newRecord, db);
|
|
||||||
Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newRecord.FullPath));
|
|
||||||
db.UpdateRecord(volume, newRecord);
|
db.UpdateRecord(volume, newRecord);
|
||||||
if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord);
|
|
||||||
if (newRecord.FullPath.Contains("$RECYCLE.BIN"))
|
var oldRecord = db.FindByFrn(volume, usn.FRN);
|
||||||
|
if (oldRecord != null)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(string.Format(">>>> Means {0} moved to recycle.", oldRecord.FullPath));
|
Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newRecord.FullPath));
|
||||||
|
if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
|
||||||
{
|
{
|
||||||
USNRecord record = USNRecord.ParseUSN(volume, usn);
|
USNRecord record = USNRecord.ParseUSN(volume, usn);
|
||||||
//string fullpath = record.Name;
|
|
||||||
//db.FindRecordPath(record, ref fullpath, db.GetVolumeRecords(volume));
|
|
||||||
//record.FullPath = fullpath;
|
|
||||||
db.AddRecord(volume, record);
|
db.AddRecord(volume, record);
|
||||||
MFTSearcher.FillPath(volume, record, db);
|
|
||||||
Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath));
|
Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath));
|
||||||
if (RecordAddedEvent != null)
|
if (RecordAddedEvent != null)
|
||||||
RecordAddedEvent(record);
|
RecordAddedEvent(record);
|
||||||
|
|||||||
@@ -184,7 +184,10 @@ namespace Wox
|
|||||||
|
|
||||||
globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||||
|
|
||||||
this.Closing += MainWindow_Closing;
|
Closing += MainWindow_Closing;
|
||||||
|
//since MainWIndow implement IPublicAPI, so we need to finish ctor MainWindow object before
|
||||||
|
//PublicAPI invoke in plugin init methods. E.g FolderPlugin
|
||||||
|
ThreadPool.QueueUserWorkItem(o => Plugins.Init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pnlResult_RightMouseClickEvent(Result result)
|
void pnlResult_RightMouseClickEvent(Result result)
|
||||||
@@ -217,8 +220,6 @@ namespace Wox
|
|||||||
Top = UserSettingStorage.Instance.WindowTop;
|
Top = UserSettingStorage.Instance.WindowTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugins.Init();
|
|
||||||
|
|
||||||
InitProgressbarAnimation();
|
InitProgressbarAnimation();
|
||||||
|
|
||||||
//only works for win7+
|
//only works for win7+
|
||||||
|
|||||||
Reference in New Issue
Block a user