From 05d9b96a91168b1716a20782e9f053fa37d96b33 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 21 Mar 2026 23:18:44 +0800 Subject: [PATCH 01/44] Add Everything 1.5 SDK --- .../EverythingSDK/x64/Everything3.dll | Bin 0 -> 154792 bytes .../EverythingSDK/x86/Everything3.dll | Bin 0 -> 111272 bytes .../Flow.Launcher.Plugin.Explorer.csproj | 6 ++++++ 3 files changed, 6 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x64/Everything3.dll create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything3.dll diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x64/Everything3.dll b/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x64/Everything3.dll new file mode 100644 index 0000000000000000000000000000000000000000..be6a6f1409d4d3f61aceb8741f841ab2f7510b70 GIT binary patch literal 154792 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 PreserveNewest + + PreserveNewest + + + PreserveNewest + From 9fca73791eb3cacd314ac3bd55c9cca8b7d3cbd4 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 22 Mar 2026 01:07:14 +0800 Subject: [PATCH 02/44] Introduce Everything SDK 3 for Everything 1.5 --- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 + .../Everything/Everything3ApiDllImport.cs | 109 ++++++ .../Search/Everything/EverythingAPI.cs | 326 +++++++++++++++++- .../Everything/EverythingApiDllImport.cs | 2 +- .../Search/SearchManager.cs | 3 + 5 files changed, 435 insertions(+), 7 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index f5b8b932581..ab48d76d53e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -48,6 +48,8 @@ public Task InitAsync(PluginInitContext context) EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86")); + Everything3ApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", + Environment.Is64BitProcess ? "x64" : "x86")); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs new file mode 100644 index 00000000000..c613923345c --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + internal static class Everything3ApiDllImport + { + public static void Load(string directory) + { + var path = Path.Combine(directory, Dll); + int code = LoadLibrary(path); + if (code == 0) + { + int err = Marshal.GetLastPInvokeError(); + Marshal.ThrowExceptionForHR(err); + } + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern int LoadLibrary(string name); + private const string Dll = "Everything3.dll"; + + [DllImport(Dll, CharSet = CharSet.Unicode)] + internal static extern IntPtr Everything3_ConnectW(string instanceName); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_DestroyClient(IntPtr client); + + [DllImport(Dll)] + internal static extern IntPtr Everything3_CreateSearchState(); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_DestroySearchState(IntPtr searchState); + + [DllImport(Dll, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchTextW(IntPtr searchState, string search); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchRegex(IntPtr searchState, bool matchRegex); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchMatchPath(IntPtr searchState, bool matchPath); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchHideResultOmissions(IntPtr searchState, bool hideResultOmissions); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchViewportOffset(IntPtr searchState, nuint offset); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_SetSearchViewportCount(IntPtr searchState, nuint count); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_ClearSearchSorts(IntPtr searchState); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_AddSearchSort(IntPtr searchState, uint propertyId, bool ascending); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_ClearSearchPropertyRequests(IntPtr searchState); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_AddSearchPropertyRequest(IntPtr searchState, uint propertyId); + + [DllImport(Dll)] + internal static extern IntPtr Everything3_Search(IntPtr client, IntPtr searchState); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_DestroyResultList(IntPtr resultList); + + [DllImport(Dll)] + internal static extern nuint Everything3_GetResultListViewportCount(IntPtr resultList); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_IsFolderResult(IntPtr resultList, nuint resultIndex); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_IsRootResult(IntPtr resultList, nuint resultIndex); + + [DllImport(Dll, CharSet = CharSet.Unicode)] + internal static extern nuint Everything3_GetResultFullPathNameW(IntPtr resultList, nuint resultIndex, StringBuilder buffer, nuint bufferSizeInWChars); + + [DllImport(Dll)] + internal static extern uint Everything3_GetResultRunCount(IntPtr resultList, nuint resultIndex); + + [DllImport(Dll, CharSet = CharSet.Unicode)] + internal static extern uint Everything3_IncRunCountFromFilenameW(IntPtr client, string fileName); + + [DllImport(Dll)] + internal static extern uint Everything3_GetLastError(); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index a4e959dd9c4..120fbc9a77c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -11,6 +11,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static class EverythingApi { private const int BufferSize = 4096; + private const string Everything15AlphaInstance = "1.5a"; private static readonly SemaphoreSlim _semaphore = new(1, 1); @@ -32,11 +33,44 @@ public enum StateCode const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; + const uint EVERYTHING3_PROPERTY_ID_NAME = 0; + const uint EVERYTHING3_PROPERTY_ID_PATH = 1; + const uint EVERYTHING3_PROPERTY_ID_SIZE = 2; + const uint EVERYTHING3_PROPERTY_ID_EXTENSION = 3; + const uint EVERYTHING3_PROPERTY_ID_TYPE = 4; + const uint EVERYTHING3_PROPERTY_ID_DATE_MODIFIED = 5; + const uint EVERYTHING3_PROPERTY_ID_DATE_CREATED = 6; + const uint EVERYTHING3_PROPERTY_ID_DATE_ACCESSED = 7; + const uint EVERYTHING3_PROPERTY_ID_ATTRIBUTES = 8; + const uint EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED = 9; + const uint EVERYTHING3_PROPERTY_ID_RUN_COUNT = 10; + const uint EVERYTHING3_PROPERTY_ID_DATE_RUN = 11; + const uint EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME = 12; + + const uint EVERYTHING3_ERROR_OUT_OF_MEMORY = 0xE0000001; + const uint EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND = 0xE0000002; + const uint EVERYTHING3_ERROR_DISCONNECTED = 0xE0000003; + const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; + /// /// Checks whether the sort option is Fast Sort. /// public static bool IsFastSortOption(EverythingSortOption sortOption) { + try + { + var client = TryConnectEverything3(); + if (client != IntPtr.Zero) + { + Everything3ApiDllImport.Everything3_DestroyClient(client); + return true; + } + } + catch (DllNotFoundException) + { + // Fallback to Everything 1.4 SDK. + } + var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); // If the Everything service is not running, then this call will incorrectly report @@ -59,6 +93,13 @@ public static async ValueTask IsEverythingRunningAsync(CancellationToken t try { + var client = TryConnectEverything3(); + if (client != IntPtr.Zero) + { + Everything3ApiDllImport.Everything3_DestroyClient(client); + return true; + } + _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; @@ -98,9 +139,10 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO if (token.IsCancellationRequested) yield break; + var useRegex = false; if (option.Keyword.StartsWith("@")) { - EverythingApiDllImport.Everything_SetRegex(true); + useRegex = true; option.Keyword = option.Keyword[1..]; } @@ -117,13 +159,136 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO builder.Append($" content:\"{option.ContentSearchKeyword}\""); } - EverythingApiDllImport.Everything_SetSearchW(builder.ToString()); + var searchText = builder.ToString(); + + var client = TryConnectEverything3(); + if (client != IntPtr.Zero) + { + await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) + yield return result; + + yield break; + } + + await foreach (var result in SearchWithEverythingLegacyAsync(option, searchText, useRegex, token)) + yield return result; + } + finally + { + _semaphore.Release(); + } + } + + private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, + EverythingSearchOption option, + string searchText, + bool useRegex, + [EnumeratorCancellation] CancellationToken token) + { + IntPtr searchState = IntPtr.Zero; + IntPtr resultList = IntPtr.Zero; + try + { + searchState = Everything3ApiDllImport.Everything3_CreateSearchState(); + if (searchState == IntPtr.Zero) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + yield break; + } + + _ = Everything3ApiDllImport.Everything3_SetSearchRegex(searchState, useRegex); + _ = Everything3ApiDllImport.Everything3_SetSearchMatchPath(searchState, option.IsFullPathSearch); + _ = Everything3ApiDllImport.Everything3_SetSearchTextW(searchState, searchText); + _ = Everything3ApiDllImport.Everything3_SetSearchHideResultOmissions(searchState, true); + _ = Everything3ApiDllImport.Everything3_SetSearchViewportOffset(searchState, (nuint)option.Offset); + _ = Everything3ApiDllImport.Everything3_SetSearchViewportCount(searchState, (nuint)option.MaxCount); + + // TODO Something here hides all results. Need to investigate further. + //_ = Everything3ApiDllImport.Everything3_ClearSearchSorts(searchState); + //if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) + //{ + // _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); + //} + + //_ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); + //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_NAME); + //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH); + //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); + + if (token.IsCancellationRequested) + yield break; + + resultList = Everything3ApiDllImport.Everything3_Search(client, searchState); + if (resultList == IntPtr.Zero) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + yield break; + } + + var resultCount = Everything3ApiDllImport.Everything3_GetResultListViewportCount(resultList); + for (nuint idx = 0; idx < resultCount; ++idx) + { + if (token.IsCancellationRequested) + { + yield break; + } + + buffer.Clear(); + var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, buffer, BufferSize); + if (fullPathLength == 0) + { + continue; + } + + var fullPath = buffer.ToString(); + if (string.IsNullOrEmpty(fullPath)) + { + continue; + } + + var result = new SearchResult + { + FullPath = fullPath, + Type = Everything3ApiDllImport.Everything3_IsFolderResult(resultList, idx) + ? ResultType.Folder + : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) + ? ResultType.Volume + : ResultType.File, + Score = (int)Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx) + }; + + yield return result; + } + } + finally + { + if (resultList != IntPtr.Zero) + _ = Everything3ApiDllImport.Everything3_DestroyResultList(resultList); + + if (searchState != IntPtr.Zero) + _ = Everything3ApiDllImport.Everything3_DestroySearchState(searchState); + + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + } + + await Task.CompletedTask; + } + + private static async IAsyncEnumerable SearchWithEverythingLegacyAsync(EverythingSearchOption option, + string searchText, + bool useRegex, + [EnumeratorCancellation] CancellationToken token) + { + try + { + EverythingApiDllImport.Everything_SetRegex(useRegex); + EverythingApiDllImport.Everything_SetSearchW(searchText); EverythingApiDllImport.Everything_SetOffset(option.Offset); EverythingApiDllImport.Everything_SetMax(option.MaxCount); EverythingApiDllImport.Everything_SetSort(option.SortOption); EverythingApiDllImport.Everything_SetMatchPath(option.IsFullPathSearch); - + if (option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) { EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); @@ -152,12 +317,11 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO var result = new SearchResult { - // todo the types are wrong. Everything expects uint everywhere, but we send int just above/below. how to fix? Is EverythingApiDllImport autogenerated or handmade? FullPath = buffer.ToString(), Type = EverythingApiDllImport.Everything_IsFolderResult(idx) ? ResultType.Folder : EverythingApiDllImport.Everything_IsFileResult(idx) ? ResultType.File : ResultType.Volume, - Score = (int)EverythingApiDllImport.Everything_GetResultRunCount( (uint)idx) + Score = (int)EverythingApiDllImport.Everything_GetResultRunCount((uint)idx) }; yield return result; @@ -166,7 +330,149 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO finally { EverythingApiDllImport.Everything_Reset(); - _semaphore.Release(); + } + + await Task.CompletedTask; + } + + private static IntPtr TryConnectEverything3() + { + try + { + return Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); + } + catch (DllNotFoundException) + { + return IntPtr.Zero; + } + catch (EntryPointNotFoundException) + { + return IntPtr.Zero; + } + } + + private static bool TryConvertSortOption(EverythingSortOption sortOption, out uint propertyId, out bool ascending) + { + switch (sortOption) + { + case EverythingSortOption.NAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = true; + return true; + case EverythingSortOption.NAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = false; + return true; + case EverythingSortOption.PATH_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_PATH; + ascending = true; + return true; + case EverythingSortOption.PATH_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_PATH; + ascending = false; + return true; + case EverythingSortOption.SIZE_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_SIZE; + ascending = true; + return true; + case EverythingSortOption.SIZE_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_SIZE; + ascending = false; + return true; + case EverythingSortOption.EXTENSION_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; + ascending = true; + return true; + case EverythingSortOption.EXTENSION_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; + ascending = false; + return true; + case EverythingSortOption.TYPE_NAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_TYPE; + ascending = true; + return true; + case EverythingSortOption.TYPE_NAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_TYPE; + ascending = false; + return true; + case EverythingSortOption.DATE_CREATED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; + ascending = true; + return true; + case EverythingSortOption.DATE_CREATED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; + ascending = false; + return true; + case EverythingSortOption.DATE_MODIFIED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; + ascending = true; + return true; + case EverythingSortOption.DATE_MODIFIED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; + ascending = false; + return true; + case EverythingSortOption.ATTRIBUTES_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; + ascending = true; + return true; + case EverythingSortOption.ATTRIBUTES_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; + ascending = false; + return true; + case EverythingSortOption.FILE_LIST_FILENAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; + ascending = true; + return true; + case EverythingSortOption.FILE_LIST_FILENAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; + ascending = false; + return true; + case EverythingSortOption.RUN_COUNT_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_RUN_COUNT; + ascending = false; + return true; + case EverythingSortOption.DATE_RECENTLY_CHANGED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; + ascending = true; + return true; + case EverythingSortOption.DATE_RECENTLY_CHANGED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; + ascending = false; + return true; + case EverythingSortOption.DATE_ACCESSED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; + ascending = true; + return true; + case EverythingSortOption.DATE_ACCESSED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; + ascending = false; + return true; + case EverythingSortOption.DATE_RUN_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; + ascending = true; + return true; + case EverythingSortOption.DATE_RUN_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; + ascending = false; + return true; + default: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = true; + return false; + } + } + + private static void CheckAndThrowExceptionOnErrorFromEverything3() + { + switch (Everything3ApiDllImport.Everything3_GetLastError()) + { + case EVERYTHING3_ERROR_OUT_OF_MEMORY: + throw new MemoryErrorException(); + case EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND: + case EVERYTHING3_ERROR_DISCONNECTED: + throw new IPCErrorException(); + case EVERYTHING3_ERROR_INVALID_PARAMETER: + throw new InvalidCallException(); } } @@ -200,6 +506,14 @@ public static async Task IncrementRunCounterAsync(string fileOrFolder) await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); try { + var client = TryConnectEverything3(); + if (client != IntPtr.Zero) + { + _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder); + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + return; + } + _ = EverythingApiDllImport.Everything_IncRunCountFromFileName(fileOrFolder); } catch (Exception) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index c952a980c47..70c02cd87aa 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -126,7 +126,7 @@ public static void Load(string directory) public static extern uint Everything_GetRequestFlags(); [DllImport(DLL)] public static extern uint Everything_GetResultListRequestFlags(); - [DllImport("Everything64.dll", CharSet = CharSet.Unicode)] + [DllImport(DLL, CharSet = CharSet.Unicode)] public static extern IntPtr Everything_GetResultExtension(uint nIndex); [DllImport(DLL)] public static extern bool Everything_GetResultSize(uint nIndex, out long lpFileSize); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 28ab1d2e24b..46216f931c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -291,6 +291,9 @@ private bool UseWindowsIndexForDirectorySearch(string locationPath) private bool IsExcludedFile(SearchResult result) { + if (string.IsNullOrEmpty(result.FullPath)) + return false; + string[] excludedFileTypes = Settings.ExcludedFileTypes.Split([','], StringSplitOptions.RemoveEmptyEntries); string fileExtension = Path.GetExtension(result.FullPath).TrimStart('.'); From 84edda4827574a936d0e64f1b53da148b9b9add5 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:36:38 +0800 Subject: [PATCH 03/44] Fix missing search --- .../Search/Everything/EverythingAPI.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 120fbc9a77c..188575df3f2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -203,17 +203,10 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_SetSearchViewportOffset(searchState, (nuint)option.Offset); _ = Everything3ApiDllImport.Everything3_SetSearchViewportCount(searchState, (nuint)option.MaxCount); - // TODO Something here hides all results. Need to investigate further. - //_ = Everything3ApiDllImport.Everything3_ClearSearchSorts(searchState); - //if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) - //{ - // _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); - //} - - //_ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); - //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_NAME); - //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH); - //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); + if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) + { + _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); + } if (token.IsCancellationRequested) yield break; From 9d1c0aec1f887ce19e1de92ef320728c58cc41b6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:12:47 +0800 Subject: [PATCH 04/44] Add fast sort detection --- .../Everything/Everything3ApiDllImport.cs | 5 ++ .../Search/Everything/EverythingAPI.cs | 71 ++++++++++++------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index c613923345c..82138f0894f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -105,5 +105,10 @@ public static void Load(string directory) [DllImport(Dll)] internal static extern uint Everything3_GetLastError(); + + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_IsPropertyFastSort(IntPtr client, uint propertyId); } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 188575df3f2..612f5f19dc9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -15,7 +15,7 @@ public static class EverythingApi private static readonly SemaphoreSlim _semaphore = new(1, 1); - // cached buffer to remove redundant allocations. + // cached buffer to remove redundant allocations. semaphore is used to make sure the access to the buffer is thread safe. private static readonly StringBuilder buffer = new(BufferSize); public enum StateCode @@ -57,18 +57,26 @@ public enum StateCode /// public static bool IsFastSortOption(EverythingSortOption sortOption) { - try + if (TryConnectEverything3(out var client)) { - var client = TryConnectEverything3(); - if (client != IntPtr.Zero) + try { - Everything3ApiDllImport.Everything3_DestroyClient(client); - return true; + if (TryConvertSortOption(sortOption, out var propertyId, out _)) + { + var isFastSort = Everything3ApiDllImport.Everything3_IsPropertyFastSort(client, propertyId); + + // Keep the same behavior as legacy path: throw when engine is not available. + CheckAndThrowExceptionOnErrorFromEverything3(); + + return isFastSort; + } + } + finally + { + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + // Throw again to the caller + CheckAndThrowExceptionOnErrorFromEverything3(); } - } - catch (DllNotFoundException) - { - // Fallback to Everything 1.4 SDK. } var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); @@ -93,12 +101,8 @@ public static async ValueTask IsEverythingRunningAsync(CancellationToken t try { - var client = TryConnectEverything3(); - if (client != IntPtr.Zero) - { - Everything3ApiDllImport.Everything3_DestroyClient(client); + if (TryUseEverything3Client(static _ => { })) return true; - } _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; @@ -161,8 +165,7 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO var searchText = builder.ToString(); - var client = TryConnectEverything3(); - if (client != IntPtr.Zero) + if (TryConnectEverything3(out var client)) { await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) yield return result; @@ -328,19 +331,37 @@ private static async IAsyncEnumerable SearchWithEverythingLegacyAs await Task.CompletedTask; } - private static IntPtr TryConnectEverything3() + private static bool TryUseEverything3Client(Action action) + { + if (!TryConnectEverything3(out var client)) + return false; + + try + { + action(client); + return true; + } + finally + { + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + } + } + + private static bool TryConnectEverything3(out IntPtr client) { + client = IntPtr.Zero; try { - return Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); + client = Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); + return client != IntPtr.Zero; } catch (DllNotFoundException) { - return IntPtr.Zero; + return false; } catch (EntryPointNotFoundException) { - return IntPtr.Zero; + return false; } } @@ -499,13 +520,9 @@ public static async Task IncrementRunCounterAsync(string fileOrFolder) await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); try { - var client = TryConnectEverything3(); - if (client != IntPtr.Zero) - { - _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder); - _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + if (TryUseEverything3Client(client => + _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder))) return; - } _ = EverythingApiDllImport.Everything_IncRunCountFromFileName(fileOrFolder); } From 9246dea855d25669925cd7662ae9801efaa38b8b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:48:33 +0800 Subject: [PATCH 05/44] Add highlight --- .../Everything/Everything3ApiDllImport.cs | 14 +++++++ .../Search/Everything/EverythingAPI.cs | 37 ++++++++++++++++++- .../Search/ResultManager.cs | 4 +- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index 82138f0894f..4514a1549f3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -76,6 +76,14 @@ public static void Load(string directory) [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool Everything3_AddSearchPropertyRequest(IntPtr searchState, uint propertyId); + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_AddSearchPropertyRequestHighlighted(IntPtr searchState, uint propertyId); + + [DllImport(Dll)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Everything3_GetSearchPropertyRequestHighlight(IntPtr searchState, nuint index); + [DllImport(Dll)] internal static extern IntPtr Everything3_Search(IntPtr client, IntPtr searchState); @@ -97,6 +105,12 @@ public static void Load(string directory) [DllImport(Dll, CharSet = CharSet.Unicode)] internal static extern nuint Everything3_GetResultFullPathNameW(IntPtr resultList, nuint resultIndex, StringBuilder buffer, nuint bufferSizeInWChars); + [DllImport(Dll, CharSet = CharSet.Unicode)] + internal static extern nuint Everything3_GetResultPropertyTextHighlightedW(IntPtr resultList, nuint resultIndex, uint propertyId, StringBuilder buffer, nuint bufferSizeInWChars); + + [DllImport(Dll, CharSet = CharSet.Unicode)] + internal static extern nuint Everything3_GetResultPropertyTextW(IntPtr resultList, nuint resultIndex, uint propertyId, StringBuilder buffer, nuint bufferSizeInWChars); + [DllImport(Dll)] internal static extern uint Everything3_GetResultRunCount(IntPtr resultList, nuint resultIndex); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 95215935c24..7bd421b8be8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -46,11 +46,13 @@ public enum StateCode const uint EVERYTHING3_PROPERTY_ID_RUN_COUNT = 10; const uint EVERYTHING3_PROPERTY_ID_DATE_RUN = 11; const uint EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME = 12; + const uint EVERYTHING3_PROPERTY_ID_PATH_AND_NAME = 240; const uint EVERYTHING3_ERROR_OUT_OF_MEMORY = 0xE0000001; const uint EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND = 0xE0000002; const uint EVERYTHING3_ERROR_DISCONNECTED = 0xE0000003; const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; + const uint EVERYTHING3_ERROR_PROPERTY_NOT_FOUND = 0xE0000007; /// /// Checks whether the sort option is Fast Sort. @@ -211,6 +213,12 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); } + _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); + // TODO somehow error, no result + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); + // TODO need to check the "IsFullPathSearch" + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); + if (token.IsCancellationRequested) yield break; @@ -233,6 +241,7 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, buffer, BufferSize); if (fullPathLength == 0) { + CheckAndThrowExceptionOnErrorFromEverything3(); continue; } @@ -250,9 +259,33 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) ? ResultType.Volume : ResultType.File, - Score = (int)Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx) + Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)) }; + // 0 for the first requested property, which is name in our case. + if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) + { + buffer.Clear(); + var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( + resultList, + idx, + EVERYTHING3_PROPERTY_ID_NAME, + buffer, + BufferSize); + + if (highlightedFileNameLength > 0) + { + var highlightData = EverythingHighlightStringToHighlightList(buffer.ToString()); + if (highlightData.Count > 0) + { + result = result with + { + HighlightData = highlightData + }; + } + } + } + yield return result; } } @@ -488,6 +521,8 @@ private static void CheckAndThrowExceptionOnErrorFromEverything3() throw new IPCErrorException(); case EVERYTHING3_ERROR_INVALID_PARAMETER: throw new InvalidCallException(); + case EVERYTHING3_ERROR_PROPERTY_NOT_FOUND: + throw new ArgumentException("EVERYTHING3_ERROR_PROPERTY_NOT_FOUND"); } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index 6c33f5ffb63..56a63735628 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -145,7 +145,7 @@ internal static Result CreateFolderResult(string title, string subtitle, string IcoPath = path, SubTitle = subtitle, AutoCompleteText = GetAutoCompleteText(title, query, path, ResultType.Folder), - TitleHighlightData = highlightData ?? Context.API.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = highlightData ?? Context.API.FuzzySearch(query.Search, title).MatchData, // TODO if length is 0 CopyText = path, Preview = new Result.PreviewInfo { @@ -347,7 +347,7 @@ internal static Result CreateFileResult(string filePath, Query query, int score FilePath = filePath, }, AutoCompleteText = GetAutoCompleteText(title, query, filePath, ResultType.File), - TitleHighlightData = highlightData ?? Context.API.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = highlightData ?? Context.API.FuzzySearch(query.Search, title).MatchData, // TODO if length is 0 Score = score, CopyText = filePath, PreviewPanel = new Lazy(() => new PreviewPanel(Settings, filePath, ResultType.File)), From 5fbb520d78858a81d7e002fca79bba4be6e52c88 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 28 Mar 2026 15:05:40 +0800 Subject: [PATCH 06/44] Fix highlighting issue --- .../Search/Everything/EverythingAPI.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 7bd421b8be8..043cb2ab8de 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -214,10 +214,11 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I } _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); - // TODO somehow error, no result _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); - // TODO need to check the "IsFullPathSearch" _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); + // Everything3_GetResultFullPathNameW requires PATH_AND_NAME to be requested + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); if (token.IsCancellationRequested) yield break; From 4bf530be2886e20b6a7a39b9967632bc2d19f5f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 11:13:02 +0000 Subject: [PATCH 07/44] Fix LoadLibrary return type to IntPtr and use Win32Exception for error handling Agent-Logs-Url: https://github.com/Flow-Launcher/Flow.Launcher/sessions/bfa04540-ad54-4f04-a7cf-fed5dbc06dcc Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> --- .../Search/Everything/Everything3ApiDllImport.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index 4514a1549f3..e2ca1bd2162 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -10,16 +11,15 @@ internal static class Everything3ApiDllImport public static void Load(string directory) { var path = Path.Combine(directory, Dll); - int code = LoadLibrary(path); - if (code == 0) + IntPtr handle = LoadLibrary(path); + if (handle == IntPtr.Zero) { - int err = Marshal.GetLastPInvokeError(); - Marshal.ThrowExceptionForHR(err); + throw new Win32Exception(Marshal.GetLastPInvokeError()); } } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern int LoadLibrary(string name); + private static extern IntPtr LoadLibrary(string name); private const string Dll = "Everything3.dll"; [DllImport(Dll, CharSet = CharSet.Unicode)] From cc6236256c59ffa78643c8bce914d83c9fee893c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 28 Mar 2026 19:37:22 +0800 Subject: [PATCH 08/44] Fix LoadLibrary return type to IntPtr and use Win32Exception for error handling --- .../Search/Everything/EverythingApiDllImport.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index 344c1a42c16..e5088b79e54 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -10,16 +11,15 @@ public static class EverythingApiDllImport public static void Load(string directory) { var path = Path.Combine(directory, DLL); - int code = LoadLibrary(path); - if (code == 0) + IntPtr handle = LoadLibrary(path); + if (handle == IntPtr.Zero) { - int err = Marshal.GetLastPInvokeError(); - Marshal.ThrowExceptionForHR(err); + throw new Win32Exception(Marshal.GetLastPInvokeError()); } } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - private static extern int LoadLibrary(string name); + private static extern IntPtr LoadLibrary(string name); private const string DLL = "Everything.dll"; From e5cc9112dfb6bcaacd946d7f63626c4d750c62d0 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 28 Mar 2026 19:44:51 +0800 Subject: [PATCH 09/44] Extract Everything3 functions --- .../Everything/EverythingAPI.Everything3.cs | 316 ++++++++++++++++++ .../Search/Everything/EverythingAPI.cs | 305 +---------------- 2 files changed, 317 insertions(+), 304 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs new file mode 100644 index 00000000000..9aef87e0f3f --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs @@ -0,0 +1,316 @@ +using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public static partial class EverythingApi + { + private const string Everything15AlphaInstance = "1.5a"; + + const uint EVERYTHING3_PROPERTY_ID_NAME = 0; + const uint EVERYTHING3_PROPERTY_ID_PATH = 1; + const uint EVERYTHING3_PROPERTY_ID_SIZE = 2; + const uint EVERYTHING3_PROPERTY_ID_EXTENSION = 3; + const uint EVERYTHING3_PROPERTY_ID_TYPE = 4; + const uint EVERYTHING3_PROPERTY_ID_DATE_MODIFIED = 5; + const uint EVERYTHING3_PROPERTY_ID_DATE_CREATED = 6; + const uint EVERYTHING3_PROPERTY_ID_DATE_ACCESSED = 7; + const uint EVERYTHING3_PROPERTY_ID_ATTRIBUTES = 8; + const uint EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED = 9; + const uint EVERYTHING3_PROPERTY_ID_RUN_COUNT = 10; + const uint EVERYTHING3_PROPERTY_ID_DATE_RUN = 11; + const uint EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME = 12; + const uint EVERYTHING3_PROPERTY_ID_PATH_AND_NAME = 240; + + const uint EVERYTHING3_ERROR_OUT_OF_MEMORY = 0xE0000001; + const uint EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND = 0xE0000002; + const uint EVERYTHING3_ERROR_DISCONNECTED = 0xE0000003; + const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; + const uint EVERYTHING3_ERROR_PROPERTY_NOT_FOUND = 0xE0000007; + + private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, + EverythingSearchOption option, + string searchText, + bool useRegex, + [EnumeratorCancellation] CancellationToken token) + { + IntPtr searchState = IntPtr.Zero; + IntPtr resultList = IntPtr.Zero; + try + { + searchState = Everything3ApiDllImport.Everything3_CreateSearchState(); + if (searchState == IntPtr.Zero) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + yield break; + } + + _ = Everything3ApiDllImport.Everything3_SetSearchRegex(searchState, useRegex); + _ = Everything3ApiDllImport.Everything3_SetSearchMatchPath(searchState, option.IsFullPathSearch); + _ = Everything3ApiDllImport.Everything3_SetSearchTextW(searchState, searchText); + _ = Everything3ApiDllImport.Everything3_SetSearchHideResultOmissions(searchState, true); + _ = Everything3ApiDllImport.Everything3_SetSearchViewportOffset(searchState, (nuint)option.Offset); + _ = Everything3ApiDllImport.Everything3_SetSearchViewportCount(searchState, (nuint)option.MaxCount); + + if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) + { + _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); + } + + _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); + // Everything3_GetResultFullPathNameW requires PATH_AND_NAME to be requested + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); + + if (token.IsCancellationRequested) + yield break; + + resultList = Everything3ApiDllImport.Everything3_Search(client, searchState); + if (resultList == IntPtr.Zero) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + yield break; + } + + var resultCount = Everything3ApiDllImport.Everything3_GetResultListViewportCount(resultList); + for (nuint idx = 0; idx < resultCount; ++idx) + { + if (token.IsCancellationRequested) + { + yield break; + } + + buffer.Clear(); + var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, buffer, BufferSize); + if (fullPathLength == 0) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + continue; + } + + var fullPath = buffer.ToString(); + if (string.IsNullOrEmpty(fullPath)) + { + continue; + } + + var result = new SearchResult + { + FullPath = fullPath, + Type = Everything3ApiDllImport.Everything3_IsFolderResult(resultList, idx) + ? ResultType.Folder + : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) + ? ResultType.Volume + : ResultType.File, + Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)) + }; + + // 0 for the first requested property, which is name in our case. + if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) + { + buffer.Clear(); + var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( + resultList, + idx, + EVERYTHING3_PROPERTY_ID_NAME, + buffer, + BufferSize); + + if (highlightedFileNameLength > 0) + { + var highlightData = EverythingHighlightStringToHighlightList(buffer.ToString()); + if (highlightData.Count > 0) + { + result = result with + { + HighlightData = highlightData + }; + } + } + } + + yield return result; + } + } + finally + { + if (resultList != IntPtr.Zero) + _ = Everything3ApiDllImport.Everything3_DestroyResultList(resultList); + + if (searchState != IntPtr.Zero) + _ = Everything3ApiDllImport.Everything3_DestroySearchState(searchState); + + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + } + + await Task.CompletedTask; + } + + private static bool TryUseEverything3Client(Action action) + { + if (!TryConnectEverything3(out var client)) + return false; + + try + { + action(client); + return true; + } + finally + { + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + } + } + + private static bool TryConnectEverything3(out IntPtr client) + { + client = IntPtr.Zero; + try + { + client = Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); + return client != IntPtr.Zero; + } + catch (DllNotFoundException) + { + return false; + } + catch (EntryPointNotFoundException) + { + return false; + } + } + + private static bool TryConvertSortOption(EverythingSortOption sortOption, out uint propertyId, out bool ascending) + { + switch (sortOption) + { + case EverythingSortOption.NAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = true; + return true; + case EverythingSortOption.NAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = false; + return true; + case EverythingSortOption.PATH_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_PATH; + ascending = true; + return true; + case EverythingSortOption.PATH_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_PATH; + ascending = false; + return true; + case EverythingSortOption.SIZE_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_SIZE; + ascending = true; + return true; + case EverythingSortOption.SIZE_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_SIZE; + ascending = false; + return true; + case EverythingSortOption.EXTENSION_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; + ascending = true; + return true; + case EverythingSortOption.EXTENSION_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; + ascending = false; + return true; + case EverythingSortOption.TYPE_NAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_TYPE; + ascending = true; + return true; + case EverythingSortOption.TYPE_NAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_TYPE; + ascending = false; + return true; + case EverythingSortOption.DATE_CREATED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; + ascending = true; + return true; + case EverythingSortOption.DATE_CREATED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; + ascending = false; + return true; + case EverythingSortOption.DATE_MODIFIED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; + ascending = true; + return true; + case EverythingSortOption.DATE_MODIFIED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; + ascending = false; + return true; + case EverythingSortOption.ATTRIBUTES_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; + ascending = true; + return true; + case EverythingSortOption.ATTRIBUTES_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; + ascending = false; + return true; + case EverythingSortOption.FILE_LIST_FILENAME_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; + ascending = true; + return true; + case EverythingSortOption.FILE_LIST_FILENAME_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; + ascending = false; + return true; + case EverythingSortOption.RUN_COUNT_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_RUN_COUNT; + ascending = false; + return true; + case EverythingSortOption.DATE_RECENTLY_CHANGED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; + ascending = true; + return true; + case EverythingSortOption.DATE_RECENTLY_CHANGED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; + ascending = false; + return true; + case EverythingSortOption.DATE_ACCESSED_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; + ascending = true; + return true; + case EverythingSortOption.DATE_ACCESSED_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; + ascending = false; + return true; + case EverythingSortOption.DATE_RUN_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; + ascending = true; + return true; + case EverythingSortOption.DATE_RUN_DESCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; + ascending = false; + return true; + default: + propertyId = EVERYTHING3_PROPERTY_ID_NAME; + ascending = true; + return false; + } + } + + private static void CheckAndThrowExceptionOnErrorFromEverything3() + { + switch (Everything3ApiDllImport.Everything3_GetLastError()) + { + case EVERYTHING3_ERROR_OUT_OF_MEMORY: + throw new MemoryErrorException(); + case EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND: + case EVERYTHING3_ERROR_DISCONNECTED: + throw new IPCErrorException(); + case EVERYTHING3_ERROR_INVALID_PARAMETER: + throw new InvalidCallException(); + case EVERYTHING3_ERROR_PROPERTY_NOT_FOUND: + throw new ArgumentException("EVERYTHING3_ERROR_PROPERTY_NOT_FOUND"); + } + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 043cb2ab8de..0c60787a4ff 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -8,10 +8,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public static class EverythingApi + public static partial class EverythingApi { private const int BufferSize = 4096; - private const string Everything15AlphaInstance = "1.5a"; private static readonly SemaphoreSlim _semaphore = new(1, 1); @@ -33,27 +32,6 @@ public enum StateCode const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; - const uint EVERYTHING3_PROPERTY_ID_NAME = 0; - const uint EVERYTHING3_PROPERTY_ID_PATH = 1; - const uint EVERYTHING3_PROPERTY_ID_SIZE = 2; - const uint EVERYTHING3_PROPERTY_ID_EXTENSION = 3; - const uint EVERYTHING3_PROPERTY_ID_TYPE = 4; - const uint EVERYTHING3_PROPERTY_ID_DATE_MODIFIED = 5; - const uint EVERYTHING3_PROPERTY_ID_DATE_CREATED = 6; - const uint EVERYTHING3_PROPERTY_ID_DATE_ACCESSED = 7; - const uint EVERYTHING3_PROPERTY_ID_ATTRIBUTES = 8; - const uint EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED = 9; - const uint EVERYTHING3_PROPERTY_ID_RUN_COUNT = 10; - const uint EVERYTHING3_PROPERTY_ID_DATE_RUN = 11; - const uint EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME = 12; - const uint EVERYTHING3_PROPERTY_ID_PATH_AND_NAME = 240; - - const uint EVERYTHING3_ERROR_OUT_OF_MEMORY = 0xE0000001; - const uint EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND = 0xE0000002; - const uint EVERYTHING3_ERROR_DISCONNECTED = 0xE0000003; - const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; - const uint EVERYTHING3_ERROR_PROPERTY_NOT_FOUND = 0xE0000007; - /// /// Checks whether the sort option is Fast Sort. /// @@ -184,126 +162,6 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO } } - private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, - EverythingSearchOption option, - string searchText, - bool useRegex, - [EnumeratorCancellation] CancellationToken token) - { - IntPtr searchState = IntPtr.Zero; - IntPtr resultList = IntPtr.Zero; - try - { - searchState = Everything3ApiDllImport.Everything3_CreateSearchState(); - if (searchState == IntPtr.Zero) - { - CheckAndThrowExceptionOnErrorFromEverything3(); - yield break; - } - - _ = Everything3ApiDllImport.Everything3_SetSearchRegex(searchState, useRegex); - _ = Everything3ApiDllImport.Everything3_SetSearchMatchPath(searchState, option.IsFullPathSearch); - _ = Everything3ApiDllImport.Everything3_SetSearchTextW(searchState, searchText); - _ = Everything3ApiDllImport.Everything3_SetSearchHideResultOmissions(searchState, true); - _ = Everything3ApiDllImport.Everything3_SetSearchViewportOffset(searchState, (nuint)option.Offset); - _ = Everything3ApiDllImport.Everything3_SetSearchViewportCount(searchState, (nuint)option.MaxCount); - - if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) - { - _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); - } - - _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); - // Everything3_GetResultFullPathNameW requires PATH_AND_NAME to be requested - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); - - if (token.IsCancellationRequested) - yield break; - - resultList = Everything3ApiDllImport.Everything3_Search(client, searchState); - if (resultList == IntPtr.Zero) - { - CheckAndThrowExceptionOnErrorFromEverything3(); - yield break; - } - - var resultCount = Everything3ApiDllImport.Everything3_GetResultListViewportCount(resultList); - for (nuint idx = 0; idx < resultCount; ++idx) - { - if (token.IsCancellationRequested) - { - yield break; - } - - buffer.Clear(); - var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, buffer, BufferSize); - if (fullPathLength == 0) - { - CheckAndThrowExceptionOnErrorFromEverything3(); - continue; - } - - var fullPath = buffer.ToString(); - if (string.IsNullOrEmpty(fullPath)) - { - continue; - } - - var result = new SearchResult - { - FullPath = fullPath, - Type = Everything3ApiDllImport.Everything3_IsFolderResult(resultList, idx) - ? ResultType.Folder - : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) - ? ResultType.Volume - : ResultType.File, - Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)) - }; - - // 0 for the first requested property, which is name in our case. - if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) - { - buffer.Clear(); - var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( - resultList, - idx, - EVERYTHING3_PROPERTY_ID_NAME, - buffer, - BufferSize); - - if (highlightedFileNameLength > 0) - { - var highlightData = EverythingHighlightStringToHighlightList(buffer.ToString()); - if (highlightData.Count > 0) - { - result = result with - { - HighlightData = highlightData - }; - } - } - } - - yield return result; - } - } - finally - { - if (resultList != IntPtr.Zero) - _ = Everything3ApiDllImport.Everything3_DestroyResultList(resultList); - - if (searchState != IntPtr.Zero) - _ = Everything3ApiDllImport.Everything3_DestroySearchState(searchState); - - _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - } - - await Task.CompletedTask; - } - private static async IAsyncEnumerable SearchWithEverythingLegacyAsync(EverythingSearchOption option, string searchText, bool useRegex, @@ -366,167 +224,6 @@ private static async IAsyncEnumerable SearchWithEverythingLegacyAs await Task.CompletedTask; } - private static bool TryUseEverything3Client(Action action) - { - if (!TryConnectEverything3(out var client)) - return false; - - try - { - action(client); - return true; - } - finally - { - _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - } - } - - private static bool TryConnectEverything3(out IntPtr client) - { - client = IntPtr.Zero; - try - { - client = Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); - return client != IntPtr.Zero; - } - catch (DllNotFoundException) - { - return false; - } - catch (EntryPointNotFoundException) - { - return false; - } - } - - private static bool TryConvertSortOption(EverythingSortOption sortOption, out uint propertyId, out bool ascending) - { - switch (sortOption) - { - case EverythingSortOption.NAME_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_NAME; - ascending = true; - return true; - case EverythingSortOption.NAME_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_NAME; - ascending = false; - return true; - case EverythingSortOption.PATH_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_PATH; - ascending = true; - return true; - case EverythingSortOption.PATH_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_PATH; - ascending = false; - return true; - case EverythingSortOption.SIZE_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_SIZE; - ascending = true; - return true; - case EverythingSortOption.SIZE_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_SIZE; - ascending = false; - return true; - case EverythingSortOption.EXTENSION_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; - ascending = true; - return true; - case EverythingSortOption.EXTENSION_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_EXTENSION; - ascending = false; - return true; - case EverythingSortOption.TYPE_NAME_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_TYPE; - ascending = true; - return true; - case EverythingSortOption.TYPE_NAME_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_TYPE; - ascending = false; - return true; - case EverythingSortOption.DATE_CREATED_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; - ascending = true; - return true; - case EverythingSortOption.DATE_CREATED_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_CREATED; - ascending = false; - return true; - case EverythingSortOption.DATE_MODIFIED_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; - ascending = true; - return true; - case EverythingSortOption.DATE_MODIFIED_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_MODIFIED; - ascending = false; - return true; - case EverythingSortOption.ATTRIBUTES_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; - ascending = true; - return true; - case EverythingSortOption.ATTRIBUTES_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_ATTRIBUTES; - ascending = false; - return true; - case EverythingSortOption.FILE_LIST_FILENAME_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; - ascending = true; - return true; - case EverythingSortOption.FILE_LIST_FILENAME_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; - ascending = false; - return true; - case EverythingSortOption.RUN_COUNT_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_RUN_COUNT; - ascending = false; - return true; - case EverythingSortOption.DATE_RECENTLY_CHANGED_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; - ascending = true; - return true; - case EverythingSortOption.DATE_RECENTLY_CHANGED_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_RECENTLY_CHANGED; - ascending = false; - return true; - case EverythingSortOption.DATE_ACCESSED_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; - ascending = true; - return true; - case EverythingSortOption.DATE_ACCESSED_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_ACCESSED; - ascending = false; - return true; - case EverythingSortOption.DATE_RUN_ASCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; - ascending = true; - return true; - case EverythingSortOption.DATE_RUN_DESCENDING: - propertyId = EVERYTHING3_PROPERTY_ID_DATE_RUN; - ascending = false; - return true; - default: - propertyId = EVERYTHING3_PROPERTY_ID_NAME; - ascending = true; - return false; - } - } - - private static void CheckAndThrowExceptionOnErrorFromEverything3() - { - switch (Everything3ApiDllImport.Everything3_GetLastError()) - { - case EVERYTHING3_ERROR_OUT_OF_MEMORY: - throw new MemoryErrorException(); - case EVERYTHING3_ERROR_IPC_PIPE_NOT_FOUND: - case EVERYTHING3_ERROR_DISCONNECTED: - throw new IPCErrorException(); - case EVERYTHING3_ERROR_INVALID_PARAMETER: - throw new InvalidCallException(); - case EVERYTHING3_ERROR_PROPERTY_NOT_FOUND: - throw new ArgumentException("EVERYTHING3_ERROR_PROPERTY_NOT_FOUND"); - } - } - private static void CheckAndThrowExceptionOnError() { switch (EverythingApiDllImport.Everything_GetLastError()) From 9eeadfe135b80b0a388910006ac4a36df730a732 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 28 Mar 2026 20:20:10 +0800 Subject: [PATCH 10/44] Add option for Everything 1.5 support --- .../Languages/en.xaml | 1 + Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 7 ++- .../Everything/Everything3ApiDllImport.cs | 27 +++++++++- .../Everything/EverythingAPI.Everything3.cs | 4 ++ .../Search/Everything/EverythingAPI.cs | 53 ++++++++++++++++--- .../Everything/EverythingApiDllImport.cs | 26 ++++++++- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 1 + .../ViewModels/SettingsViewModel.cs | 20 +++++++ .../Views/ExplorerSettings.xaml | 23 +++++--- 9 files changed, 140 insertions(+), 22 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 1eae757083c..e05b0135008 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -186,6 +186,7 @@ Search Full Path Enable File/Folder Run Count + Enable Everything 1.5 support Click to launch or install Everything Everything Installation diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index ab48d76d53e..7a77c17dc2f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -46,10 +46,9 @@ public Task InitAsync(PluginInitContext context) searchManager = new SearchManager(Settings, Context); ResultManager.Init(Context, Settings); - EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", - Environment.Is64BitProcess ? "x64" : "x86")); - Everything3ApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", - Environment.Is64BitProcess ? "x64" : "x86")); + var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", + Environment.Is64BitProcess ? "x64" : "x86"); + EverythingApi.ConfigureEverythingSupport(Settings.EnableEverything15Support, sdkDirectory); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index e2ca1bd2162..2ca04bb4798 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -8,18 +8,41 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { internal static class Everything3ApiDllImport { + private static IntPtr _dllHandle = IntPtr.Zero; + public static void Load(string directory) { + if (_dllHandle != IntPtr.Zero) + { + return; + } + var path = Path.Combine(directory, Dll); - IntPtr handle = LoadLibrary(path); - if (handle == IntPtr.Zero) + _dllHandle = LoadLibrary(path); + if (_dllHandle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastPInvokeError()); } } + public static void Unload() + { + if (_dllHandle == IntPtr.Zero) + { + return; + } + + _ = FreeLibrary(_dllHandle); + _dllHandle = IntPtr.Zero; + } + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string name); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool FreeLibrary(IntPtr hModule); + private const string Dll = "Everything3.dll"; [DllImport(Dll, CharSet = CharSet.Unicode)] diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs index 9aef87e0f3f..e9a8eedbde3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs @@ -171,6 +171,10 @@ private static bool TryUseEverything3Client(Action action) private static bool TryConnectEverything3(out IntPtr client) { client = IntPtr.Zero; + + if (!EnableEverything15Support) + return false; + try { client = Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 0c60787a4ff..a12bc4c0e83 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -13,6 +13,7 @@ public static partial class EverythingApi private const int BufferSize = 4096; private static readonly SemaphoreSlim _semaphore = new(1, 1); + private static volatile bool _enableEverything15Support = true; // cached buffer to remove redundant allocations. semaphore is used to make sure the access to the buffer is thread safe. private static readonly StringBuilder buffer = new(BufferSize); @@ -32,13 +33,42 @@ public enum StateCode const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; + public static bool EnableEverything15Support => _enableEverything15Support; + + public static void ConfigureEverythingSupport(bool enableEverything15Support, string sdkDirectory) + { + _semaphore.Wait(); + try + { + _enableEverything15Support = enableEverything15Support; + + if (enableEverything15Support) + { + EverythingApiDllImport.Unload(); + Everything3ApiDllImport.Load(sdkDirectory); + } + else + { + Everything3ApiDllImport.Unload(); + EverythingApiDllImport.Load(sdkDirectory); + } + } + finally + { + _semaphore.Release(); + } + } + /// /// Checks whether the sort option is Fast Sort. /// public static bool IsFastSortOption(EverythingSortOption sortOption) { - if (TryConnectEverything3(out var client)) + if (EnableEverything15Support) { + if (!TryConnectEverything3(out var client)) + throw new IPCErrorException(); + try { if (TryConvertSortOption(sortOption, out var propertyId, out _)) @@ -57,6 +87,8 @@ public static bool IsFastSortOption(EverythingSortOption sortOption) // Throw again to the caller CheckAndThrowExceptionOnErrorFromEverything3(); } + + return true; } var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); @@ -81,12 +113,11 @@ public static async ValueTask IsEverythingRunningAsync(CancellationToken t try { - if (TryUseEverything3Client(static _ => { })) - return true; + if (EnableEverything15Support) + return TryUseEverything3Client(static _ => { }); _ = EverythingApiDllImport.Everything_GetMajorVersion(); - var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; - return result; + return EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; } finally { @@ -145,8 +176,11 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO var searchText = builder.ToString(); - if (TryConnectEverything3(out var client)) + if (EnableEverything15Support) { + if (!TryConnectEverything3(out var client)) + throw new IPCErrorException(); + await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) yield return result; @@ -254,9 +288,12 @@ public static async Task IncrementRunCounterAsync(string fileOrFolder) await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); try { - if (TryUseEverything3Client(client => - _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder))) + if (EnableEverything15Support) + { + _ = TryUseEverything3Client(client => + _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); return; + } _ = EverythingApiDllImport.Everything_IncRunCountFromFileName(fileOrFolder); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index e5088b79e54..d31db5ab0aa 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -8,19 +8,41 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public static class EverythingApiDllImport { + private static IntPtr _dllHandle = IntPtr.Zero; + public static void Load(string directory) { + if (_dllHandle != IntPtr.Zero) + { + return; + } + var path = Path.Combine(directory, DLL); - IntPtr handle = LoadLibrary(path); - if (handle == IntPtr.Zero) + _dllHandle = LoadLibrary(path); + if (_dllHandle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastPInvokeError()); } } + public static void Unload() + { + if (_dllHandle == IntPtr.Zero) + { + return; + } + + _ = FreeLibrary(_dllHandle); + _dllHandle = IntPtr.Zero; + } + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string name); + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool FreeLibrary(IntPtr hModule); + private const string DLL = "Everything.dll"; [DllImport(DLL, CharSet = CharSet.Unicode)] diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index b0fbad84fbe..0f4162514b6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -163,6 +163,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; + public bool EnableEverything15Support { get; set; } = false; #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index a9b2e6a89e3..e81f43946f3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -666,6 +666,26 @@ public string EverythingInstalledPath } } + public bool EnableEverything15Support + { + get => Settings.EnableEverything15Support; + set + { + if (Settings.EnableEverything15Support == value) + return; + + Settings.EnableEverything15Support = value; + + var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", + Environment.Is64BitProcess ? "x64" : "x86"); + EverythingApi.ConfigureEverythingSupport(value, sdkDirectory); + + OnPropertyChanged(); + OnPropertyChanged(nameof(FastSortWarningVisibility)); + OnPropertyChanged(nameof(SortOptionWarningMessage)); + } + } + #endregion } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index d6066df953f..d0b7958d4cc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -435,6 +435,7 @@ + @@ -602,6 +603,7 @@ + @@ -614,11 +616,20 @@ Grid.ColumnSpan="2" Margin="{StaticResource SettingPanelItemTopBottomMargin}" HorizontalAlignment="Left" + Content="{DynamicResource flowlauncher_plugin_everything_enable_15_support}" + IsChecked="{Binding EnableEverything15Support}" /> + + Date: Sat, 28 Mar 2026 20:37:58 +0800 Subject: [PATCH 11/44] Allow customizing Everything 1.5 instance name --- .../Languages/en.xaml | 1 + Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 +- .../Everything/Everything3ApiDllImport.cs | 1 + .../Everything/EverythingAPI.Everything3.cs | 4 +-- .../Search/Everything/EverythingAPI.cs | 30 +++++++++++++--- .../Everything/EverythingApiDllImport.cs | 1 + .../Flow.Launcher.Plugin.Explorer/Settings.cs | 1 + .../ViewModels/SettingsViewModel.cs | 29 ++++++++++++++- .../Views/ExplorerSettings.xaml | 35 +++++++++++++++---- 9 files changed, 87 insertions(+), 17 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index e05b0135008..a0cd5316549 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -44,6 +44,7 @@ Date and time format Sort Option: Everything Path: + Everything 1.5 instance name: Launch Hidden Editor Path Shell Path diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index 7a77c17dc2f..1389d5be16d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -48,7 +48,7 @@ public Task InitAsync(PluginInitContext context) var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - EverythingApi.ConfigureEverythingSupport(Settings.EnableEverything15Support, sdkDirectory); + EverythingApi.ConfigureEverythingSupport(Settings.EnableEverything15Support, sdkDirectory, Settings.Everything15InstanceName); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index 2ca04bb4798..fbc9335ed7e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -9,6 +9,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything internal static class Everything3ApiDllImport { private static IntPtr _dllHandle = IntPtr.Zero; + internal static bool IsLoaded => _dllHandle != IntPtr.Zero; public static void Load(string directory) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs index e9a8eedbde3..8f718250397 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs @@ -9,8 +9,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public static partial class EverythingApi { - private const string Everything15AlphaInstance = "1.5a"; - const uint EVERYTHING3_PROPERTY_ID_NAME = 0; const uint EVERYTHING3_PROPERTY_ID_PATH = 1; const uint EVERYTHING3_PROPERTY_ID_SIZE = 2; @@ -177,7 +175,7 @@ private static bool TryConnectEverything3(out IntPtr client) try { - client = Everything3ApiDllImport.Everything3_ConnectW(Everything15AlphaInstance); + client = Everything3ApiDllImport.Everything3_ConnectW(Everything15InstanceName); return client != IntPtr.Zero; } catch (DllNotFoundException) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index a12bc4c0e83..c27fa825ac8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -10,10 +10,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public static partial class EverythingApi { + public const string DefaultEverything15InstanceName = "1.5a"; + private const int BufferSize = 4096; private static readonly SemaphoreSlim _semaphore = new(1, 1); private static volatile bool _enableEverything15Support = true; + private static string _everything15InstanceName = DefaultEverything15InstanceName; // cached buffer to remove redundant allocations. semaphore is used to make sure the access to the buffer is thread safe. private static readonly StringBuilder buffer = new(BufferSize); @@ -34,23 +37,40 @@ public enum StateCode const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; public static bool EnableEverything15Support => _enableEverything15Support; + public static string Everything15InstanceName => _everything15InstanceName; - public static void ConfigureEverythingSupport(bool enableEverything15Support, string sdkDirectory) + public static void ConfigureEverythingSupport(bool enableEverything15Support, string sdkDirectory, string everything15InstanceName) { _semaphore.Wait(); try { + var normalizedInstanceName = string.IsNullOrWhiteSpace(everything15InstanceName) + ? DefaultEverything15InstanceName + : everything15InstanceName.Trim(); + + var supportChanged = _enableEverything15Support != enableEverything15Support; _enableEverything15Support = enableEverything15Support; + _everything15InstanceName = normalizedInstanceName; if (enableEverything15Support) { - EverythingApiDllImport.Unload(); - Everything3ApiDllImport.Load(sdkDirectory); + if (supportChanged || !Everything3ApiDllImport.IsLoaded) + { + if (EverythingApiDllImport.IsLoaded) + EverythingApiDllImport.Unload(); + + Everything3ApiDllImport.Load(sdkDirectory); + } } else { - Everything3ApiDllImport.Unload(); - EverythingApiDllImport.Load(sdkDirectory); + if (supportChanged || !EverythingApiDllImport.IsLoaded) + { + if (Everything3ApiDllImport.IsLoaded) + Everything3ApiDllImport.Unload(); + + EverythingApiDllImport.Load(sdkDirectory); + } } } finally diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index d31db5ab0aa..3ffd80b3e09 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -9,6 +9,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static class EverythingApiDllImport { private static IntPtr _dllHandle = IntPtr.Zero; + public static bool IsLoaded => _dllHandle != IntPtr.Zero; public static void Load(string directory) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 0f4162514b6..2be694a7f40 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -164,6 +164,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; public bool EnableEverything15Support { get; set; } = false; + public string Everything15InstanceName { get; set; } = "1.5a"; #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index e81f43946f3..de28ceb9255 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -678,7 +678,7 @@ public bool EnableEverything15Support var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - EverythingApi.ConfigureEverythingSupport(value, sdkDirectory); + EverythingApi.ConfigureEverythingSupport(value, sdkDirectory, Settings.Everything15InstanceName); OnPropertyChanged(); OnPropertyChanged(nameof(FastSortWarningVisibility)); @@ -686,6 +686,33 @@ public bool EnableEverything15Support } } + public string Everything15InstanceName + { + get => Settings.Everything15InstanceName; + set + { + var instanceName = string.IsNullOrWhiteSpace(value) + ? EverythingApi.DefaultEverything15InstanceName + : value.Trim(); + + if (Settings.Everything15InstanceName == instanceName) + return; + + Settings.Everything15InstanceName = instanceName; + + if (EnableEverything15Support) + { + var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", + Environment.Is64BitProcess ? "x64" : "x86"); + EverythingApi.ConfigureEverythingSupport(true, sdkDirectory, instanceName); + OnPropertyChanged(nameof(FastSortWarningVisibility)); + OnPropertyChanged(nameof(SortOptionWarningMessage)); + } + + OnPropertyChanged(); + } + } + #endregion } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index d0b7958d4cc..90a0213c301 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -13,6 +13,8 @@ mc:Ignorable="d"> + + @@ -436,6 +438,7 @@ + @@ -604,6 +607,7 @@ + @@ -619,9 +623,26 @@ Content="{DynamicResource flowlauncher_plugin_everything_enable_15_support}" IsChecked="{Binding EnableEverything15Support}" /> - + + + Date: Sat, 28 Mar 2026 22:35:39 +0800 Subject: [PATCH 12/44] Use variable for default name Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 2be694a7f40..5ecfaa7c66c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -164,7 +164,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; public bool EnableEverything15Support { get; set; } = false; - public string Everything15InstanceName { get; set; } = "1.5a"; + public string Everything15InstanceName { get; set; } = EverythingApi.DefaultEverything15InstanceName; #endregion From 68f0f47a0d7ac455dd754b2f1a0cd7693f03f4be Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 28 Mar 2026 22:15:23 +0800 Subject: [PATCH 13/44] Clear handle after successful unload --- .../Search/Everything/Everything3ApiDllImport.cs | 6 ++++-- .../Search/Everything/EverythingApiDllImport.cs | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index fbc9335ed7e..9844330750c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -32,8 +32,10 @@ public static void Unload() { return; } - - _ = FreeLibrary(_dllHandle); + if (!FreeLibrary(_dllHandle)) + { + throw new Win32Exception(Marshal.GetLastPInvokeError()); + } _dllHandle = IntPtr.Zero; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index 3ffd80b3e09..4607badba3f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -33,7 +33,10 @@ public static void Unload() return; } - _ = FreeLibrary(_dllHandle); + if (!FreeLibrary(_dllHandle)) + { + throw new Win32Exception(Marshal.GetLastPInvokeError()); + } _dllHandle = IntPtr.Zero; } From 584ce0790b699a775301195cff5aa77a908fcee1 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 01:40:34 +0800 Subject: [PATCH 14/44] Refactor --- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 +- .../Search/Everything/EverythingAPI.cs | 235 ++---------------- .../Everything/EverythingApiDllImport.cs | 2 +- ...gAPI.Everything3.cs => EverythingApiV3.cs} | 165 ++++++++++-- .../Search/Everything/EverythingHelper.cs | 69 +++++ .../Everything/EverythingSearchManager.cs | 71 +++++- .../Search/Everything/IEverythingApi.cs | 14 ++ .../Search/ResultManager.cs | 3 +- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- .../ViewModels/SettingsViewModel.cs | 10 +- 10 files changed, 330 insertions(+), 243 deletions(-) rename Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/{EverythingAPI.Everything3.cs => EverythingApiV3.cs} (72%) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index 1389d5be16d..d872ae22b1f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -48,7 +48,7 @@ public Task InitAsync(PluginInitContext context) var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - EverythingApi.ConfigureEverythingSupport(Settings.EnableEverything15Support, sdkDirectory, Settings.Everything15InstanceName); + Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index c27fa825ac8..6ecd4b3d0c0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -1,126 +1,27 @@ -using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; -using System; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public static partial class EverythingApi + public class LegacyEverythingApi : IEverythingApi { - public const string DefaultEverything15InstanceName = "1.5a"; - private const int BufferSize = 4096; - private static readonly SemaphoreSlim _semaphore = new(1, 1); - private static volatile bool _enableEverything15Support = true; - private static string _everything15InstanceName = DefaultEverything15InstanceName; - - // cached buffer to remove redundant allocations. semaphore is used to make sure the access to the buffer is thread safe. private static readonly StringBuilder buffer = new(BufferSize); - public enum StateCode - { - OK, - MemoryError, - IPCError, - RegisterClassExError, - CreateWindowError, - CreateThreadError, - InvalidIndexError, - InvalidCallError - } - - const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; - const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; - - public static bool EnableEverything15Support => _enableEverything15Support; - public static string Everything15InstanceName => _everything15InstanceName; - - public static void ConfigureEverythingSupport(bool enableEverything15Support, string sdkDirectory, string everything15InstanceName) - { - _semaphore.Wait(); - try - { - var normalizedInstanceName = string.IsNullOrWhiteSpace(everything15InstanceName) - ? DefaultEverything15InstanceName - : everything15InstanceName.Trim(); - - var supportChanged = _enableEverything15Support != enableEverything15Support; - _enableEverything15Support = enableEverything15Support; - _everything15InstanceName = normalizedInstanceName; - - if (enableEverything15Support) - { - if (supportChanged || !Everything3ApiDllImport.IsLoaded) - { - if (EverythingApiDllImport.IsLoaded) - EverythingApiDllImport.Unload(); - - Everything3ApiDllImport.Load(sdkDirectory); - } - } - else - { - if (supportChanged || !EverythingApiDllImport.IsLoaded) - { - if (Everything3ApiDllImport.IsLoaded) - Everything3ApiDllImport.Unload(); - - EverythingApiDllImport.Load(sdkDirectory); - } - } - } - finally - { - _semaphore.Release(); - } - } - - /// - /// Checks whether the sort option is Fast Sort. - /// - public static bool IsFastSortOption(EverythingSortOption sortOption) + public bool IsFastSortOption(EverythingSortOption sortOption) { - if (EnableEverything15Support) - { - if (!TryConnectEverything3(out var client)) - throw new IPCErrorException(); - - try - { - if (TryConvertSortOption(sortOption, out var propertyId, out _)) - { - var isFastSort = Everything3ApiDllImport.Everything3_IsPropertyFastSort(client, propertyId); - - // Keep the same behavior as legacy path: throw when engine is not available. - CheckAndThrowExceptionOnErrorFromEverything3(); - - return isFastSort; - } - } - finally - { - _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - // Throw again to the caller - CheckAndThrowExceptionOnErrorFromEverything3(); - } - - return true; - } - var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); - - // If the Everything service is not running, then this call will incorrectly report - // the state as false. This checks for errors thrown by the api and up to the caller to handle. CheckAndThrowExceptionOnError(); - return fastSortOptionEnabled; } - public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) + public async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { try { @@ -133,11 +34,8 @@ public static async ValueTask IsEverythingRunningAsync(CancellationToken t try { - if (EnableEverything15Support) - return TryUseEverything3Client(static _ => { }); - _ = EverythingApiDllImport.Everything_GetMajorVersion(); - return EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; + return EverythingApiDllImport.Everything_GetLastError() != EverythingHelper.StateCode.IPCError; } finally { @@ -145,18 +43,10 @@ public static async ValueTask IsEverythingRunningAsync(CancellationToken t } } - /// - /// Searches the specified key word and reset the everything API afterwards - /// - /// Search Criteria - /// when cancelled the current search will stop and exit (and would not reset) - /// An IAsyncEnumerable that will enumerate all results searched by the specific query and option - public static async IAsyncEnumerable SearchAsync(EverythingSearchOption option, - [EnumeratorCancellation] CancellationToken token) + public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) { if (option.Offset < 0) throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); - if (option.MaxCount < 0) throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); @@ -196,33 +86,6 @@ public static async IAsyncEnumerable SearchAsync(EverythingSearchO var searchText = builder.ToString(); - if (EnableEverything15Support) - { - if (!TryConnectEverything3(out var client)) - throw new IPCErrorException(); - - await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) - yield return result; - - yield break; - } - - await foreach (var result in SearchWithEverythingLegacyAsync(option, searchText, useRegex, token)) - yield return result; - } - finally - { - _semaphore.Release(); - } - } - - private static async IAsyncEnumerable SearchWithEverythingLegacyAsync(EverythingSearchOption option, - string searchText, - bool useRegex, - [EnumeratorCancellation] CancellationToken token) - { - try - { EverythingApiDllImport.Everything_SetRegex(useRegex); EverythingApiDllImport.Everything_SetSearchW(searchText); EverythingApiDllImport.Everything_SetOffset(option.Offset); @@ -233,11 +96,11 @@ private static async IAsyncEnumerable SearchWithEverythingLegacyAs if (option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) { - EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); + EverythingApiDllImport.Everything_SetRequestFlags(0x00000004u | 0x00000400u); } else { - EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME); + EverythingApiDllImport.Everything_SetRequestFlags(0x00000004u); } if (token.IsCancellationRequested) yield break; @@ -264,7 +127,7 @@ private static async IAsyncEnumerable SearchWithEverythingLegacyAs EverythingApiDllImport.Everything_IsFileResult(idx) ? ResultType.File : ResultType.Volume, Score = Convert.ToInt32(EverythingApiDllImport.Everything_GetResultRunCount((uint)idx)), - HighlightData = EverythingHighlightStringToHighlightList(EverythingApiDllImport.Everything_GetResultHighlightedFileName((uint)idx)) + HighlightData = EverythingHelper.EverythingHighlightStringToHighlightList(EverythingApiDllImport.Everything_GetResultHighlightedFileName((uint)idx)) }; yield return result; @@ -273,6 +136,7 @@ private static async IAsyncEnumerable SearchWithEverythingLegacyAs finally { EverythingApiDllImport.Everything_Reset(); + _semaphore.Release(); } await Task.CompletedTask; @@ -282,96 +146,43 @@ private static void CheckAndThrowExceptionOnError() { switch (EverythingApiDllImport.Everything_GetLastError()) { - case StateCode.CreateThreadError: + case EverythingHelper.StateCode.CreateThreadError: throw new CreateThreadException(); - case StateCode.CreateWindowError: + case EverythingHelper.StateCode.CreateWindowError: throw new CreateWindowException(); - case StateCode.InvalidCallError: + case EverythingHelper.StateCode.InvalidCallError: throw new InvalidCallException(); - case StateCode.InvalidIndexError: + case EverythingHelper.StateCode.InvalidIndexError: throw new InvalidIndexException(); - case StateCode.IPCError: + case EverythingHelper.StateCode.IPCError: throw new IPCErrorException(); - case StateCode.MemoryError: + case EverythingHelper.StateCode.MemoryError: throw new MemoryErrorException(); - case StateCode.RegisterClassExError: + case EverythingHelper.StateCode.RegisterClassExError: throw new RegisterClassExException(); - case StateCode.OK: + case EverythingHelper.StateCode.OK: break; default: throw new ArgumentOutOfRangeException(); } } - public static async Task IncrementRunCounterAsync(string fileOrFolder) + public async Task IncrementRunCounterAsync(string fileOrFolder) { await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); try { - if (EnableEverything15Support) - { - _ = TryUseEverything3Client(client => - _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); - return; - } - _ = EverythingApiDllImport.Everything_IncRunCountFromFileName(fileOrFolder); } catch (Exception) { /*ignored*/ } - finally { _semaphore.Release(); } - } - - /// - /// Convert the highlighted string from Everything API to a list of highlight indexes for our Result. - /// - /// Text inside a * quote is highlighted, two consecutive *'s is a single literal *. For example, in the highlighted text: abc*123* the 123 part is highlighted. - /// A list of zero-based character indices that should be highlighted. - public static List EverythingHighlightStringToHighlightList(string highlightString) - { - var highlightData = new List(); - - if (string.IsNullOrEmpty(highlightString)) - return highlightData; - - var isHighlighted = false; - var actualIndex = 0; // Index in the actual string (without * markers) - var length = highlightString.Length; - - for (var i = 0; i < length; i++) + finally { - if (highlightString[i] == '*') - { - // Check if it's a literal * (two consecutive *) - if (i + 1 < length && highlightString[i + 1] == '*') - { - // Two consecutive *'s represent a single literal * - if (isHighlighted) - { - highlightData.Add(actualIndex); - } - actualIndex++; - i++; // Skip the next * - } - else - { - isHighlighted = !isHighlighted; - } - } - else - { - // Regular character - if (isHighlighted) - { - highlightData.Add(actualIndex); - } - actualIndex++; - } + _semaphore.Release(); } - - return highlightData; } + } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index 4607badba3f..ad3da871993 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -92,7 +92,7 @@ public static void Unload() internal static extern string Everything_GetSearchW(); [DllImport(DLL)] - internal static extern EverythingApi.StateCode Everything_GetLastError(); + internal static extern EverythingHelper.StateCode Everything_GetLastError(); [DllImport(DLL, CharSet = CharSet.Unicode)] internal static extern bool Everything_QueryW(bool bWait); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs similarity index 72% rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 8f718250397..7f42dfddf7b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.Everything3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -1,14 +1,28 @@ -using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; -using System; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Text; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public static partial class EverythingApi + public class EverythingApiV3 : IEverythingApi { + public const string DefaultEverything15InstanceName = "1.5a"; + + private const int BufferSize = 4096; + private static readonly SemaphoreSlim _semaphore = new(1, 1); + private static readonly StringBuilder _buffer = new(BufferSize); + + private readonly string _instanceName; + + public EverythingApiV3(string instanceName) + { + _instanceName = instanceName; + } + const uint EVERYTHING3_PROPERTY_ID_NAME = 0; const uint EVERYTHING3_PROPERTY_ID_PATH = 1; const uint EVERYTHING3_PROPERTY_ID_SIZE = 2; @@ -30,7 +44,124 @@ public static partial class EverythingApi const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; const uint EVERYTHING3_ERROR_PROPERTY_NOT_FOUND = 0xE0000007; - private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, + public async ValueTask IsEverythingRunningAsync(CancellationToken token = default) + { + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + return false; + } + + try + { + return TryUseEverything3Client(static _ => { }); + } + finally + { + _semaphore.Release(); + } + } + + public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) + { + if (option.Offset < 0) + throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); + if (option.MaxCount < 0) + throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); + + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + yield break; + } + + try + { + if (token.IsCancellationRequested) + yield break; + + var useRegex = false; + if (option.Keyword.StartsWith("@")) + { + useRegex = true; + option.Keyword = option.Keyword[1..]; + } + + var builder = new StringBuilder(); + builder.Append(option.Keyword); + + if (!string.IsNullOrWhiteSpace(option.ParentPath)) + { + builder.Append($" {(option.IsRecursive ? "" : "parent:")}\"{option.ParentPath}\""); + } + + if (option.IsContentSearch) + { + builder.Append($" content:\"{option.ContentSearchKeyword}\""); + } + + var searchText = builder.ToString(); + + if (!TryConnectEverything3(out var client)) + throw new IPCErrorException(); + + await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) + yield return result; + } + finally + { + _semaphore.Release(); + } + } + + public async Task IncrementRunCounterAsync(string fileOrFolder) + { + await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); + try + { + _ = TryUseEverything3Client(client => + _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); + } + catch (Exception) + { + /*ignored*/ + } + finally + { + _semaphore.Release(); + } + } + + public bool IsFastSortOption(EverythingSortOption sortOption) + { + if (!TryConnectEverything3(out var client)) + throw new IPCErrorException(); + + try + { + if (TryConvertSortOption(sortOption, out var propertyId, out _)) + { + var isFastSort = Everything3ApiDllImport.Everything3_IsPropertyFastSort(client, propertyId); + CheckAndThrowExceptionOnErrorFromEverything3(); + return isFastSort; + } + } + finally + { + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + CheckAndThrowExceptionOnErrorFromEverything3(); + } + + return true; + } + + private async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, EverythingSearchOption option, string searchText, bool useRegex, @@ -62,7 +193,6 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); - // Everything3_GetResultFullPathNameW requires PATH_AND_NAME to be requested _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); @@ -84,15 +214,15 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I yield break; } - buffer.Clear(); - var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, buffer, BufferSize); + _buffer.Clear(); + var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, _buffer, BufferSize); if (fullPathLength == 0) { CheckAndThrowExceptionOnErrorFromEverything3(); continue; } - var fullPath = buffer.ToString(); + var fullPath = _buffer.ToString(); if (string.IsNullOrEmpty(fullPath)) { continue; @@ -109,20 +239,19 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)) }; - // 0 for the first requested property, which is name in our case. if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) { - buffer.Clear(); + _buffer.Clear(); var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( resultList, idx, EVERYTHING3_PROPERTY_ID_NAME, - buffer, + _buffer, BufferSize); if (highlightedFileNameLength > 0) { - var highlightData = EverythingHighlightStringToHighlightList(buffer.ToString()); + var highlightData = EverythingHelper.EverythingHighlightStringToHighlightList(_buffer.ToString()); if (highlightData.Count > 0) { result = result with @@ -150,7 +279,7 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I await Task.CompletedTask; } - private static bool TryUseEverything3Client(Action action) + private bool TryUseEverything3Client(Action action) { if (!TryConnectEverything3(out var client)) return false; @@ -166,16 +295,16 @@ private static bool TryUseEverything3Client(Action action) } } - private static bool TryConnectEverything3(out IntPtr client) + private bool TryConnectEverything3(out IntPtr client) { client = IntPtr.Zero; - if (!EnableEverything15Support) - return false; - try { - client = Everything3ApiDllImport.Everything3_ConnectW(Everything15InstanceName); + var normalizedInstanceName = string.IsNullOrWhiteSpace(_instanceName) + ? DefaultEverything15InstanceName + : _instanceName.Trim(); + client = Everything3ApiDllImport.Everything3_ConnectW(normalizedInstanceName); return client != IntPtr.Zero; } catch (DllNotFoundException) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs new file mode 100644 index 00000000000..8f8db86b5c6 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public static class EverythingHelper + { + public enum StateCode + { + OK, + MemoryError, + IPCError, + RegisterClassExError, + CreateWindowError, + CreateThreadError, + InvalidIndexError, + InvalidCallError + } + + /// + /// Convert the highlighted string from Everything API to a list of highlight indexes for our Result. + /// + /// Text inside a * quote is highlighted, two consecutive *'s is a single literal *. For example, in the highlighted text: abc*123* the 123 part is highlighted. + /// A list of zero-based character indices that should be highlighted. + public static List EverythingHighlightStringToHighlightList(string highlightString) + { + var highlightData = new List(); + + if (string.IsNullOrEmpty(highlightString)) + return highlightData; + + var isHighlighted = false; + var actualIndex = 0; // Index in the actual string (without * markers) + var length = highlightString.Length; + + for (var i = 0; i < length; i++) + { + if (highlightString[i] == '*') + { + // Check if it's a literal * (two consecutive *) + if (i + 1 < length && highlightString[i + 1] == '*') + { + // Two consecutive *'s represent a single literal * + if (isHighlighted) + { + highlightData.Add(actualIndex); + } + actualIndex++; + i++; // Skip the next * + } + else + { + isHighlighted = !isHighlighted; + } + } + else + { + // Regular character + if (isHighlighted) + { + highlightData.Add(actualIndex); + } + actualIndex++; + } + } + + return highlightData; + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index eb994a6f98f..7404e1a0ed5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -12,19 +12,24 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { private static readonly string ClassName = nameof(EverythingSearchManager); + private static readonly SemaphoreSlim _dllSemaphore = new(1, 1); + private static volatile bool _dllLoadedForSdk3 = true; private Settings Settings { get; } + private readonly Lock _syncRoot = new(); + private IEverythingApi _api; public EverythingSearchManager(Settings settings) { Settings = settings; + _api = CreateApi(Settings.EnableEverything15Support, GetNormalizedInstanceName(Settings.Everything15InstanceName)); } private async ValueTask ThrowIfEverythingNotAvailableAsync(CancellationToken token = default) { try { - if (!await EverythingApi.IsEverythingRunningAsync(token)) + if (!await _api.IsEverythingRunningAsync(token)) throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), @@ -85,7 +90,7 @@ public async IAsyncEnumerable SearchAsync(string search, [Enumerat IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in EverythingApi.SearchAsync(option, token)) + await foreach (var result in _api.SearchAsync(option, token)) yield return result; } @@ -119,7 +124,7 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in EverythingApi.SearchAsync(option, token)) + await foreach (var result in _api.SearchAsync(option, token)) { yield return result; } @@ -140,8 +145,66 @@ public async IAsyncEnumerable EnumerateAsync(string path, string s IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in EverythingApi.SearchAsync(option, token)) + await foreach (var result in _api.SearchAsync(option, token)) yield return result; } + public void ReloadApi(string sdkDirectory) + { + lock (_syncRoot) + { + LoadDllCore(Settings.EnableEverything15Support, sdkDirectory); + _api = CreateApi(Settings.EnableEverything15Support, GetNormalizedInstanceName(Settings.Everything15InstanceName)); + } + } + + public bool IsFastSortOption(EverythingSortOption sortOption) => _api.IsFastSortOption(sortOption); + + public Task IncrementRunCounterAsync(string fileOrFolder) => _api.IncrementRunCounterAsync(fileOrFolder); + + private static void LoadDllCore(bool enableEverything15Support, string sdkDirectory) + { + _dllSemaphore.Wait(); + try + { + var supportChanged = _dllLoadedForSdk3 != enableEverything15Support; + _dllLoadedForSdk3 = enableEverything15Support; + + if (enableEverything15Support) + { + if (supportChanged || !Everything3ApiDllImport.IsLoaded) + { + if (EverythingApiDllImport.IsLoaded) + EverythingApiDllImport.Unload(); + + Everything3ApiDllImport.Load(sdkDirectory); + } + } + else + { + if (supportChanged || !EverythingApiDllImport.IsLoaded) + { + if (Everything3ApiDllImport.IsLoaded) + Everything3ApiDllImport.Unload(); + + EverythingApiDllImport.Load(sdkDirectory); + } + } + } + finally + { + _dllSemaphore.Release(); + } + } + + private static string GetNormalizedInstanceName(string instanceName) => string.IsNullOrWhiteSpace(instanceName) + ? EverythingApiV3.DefaultEverything15InstanceName + : instanceName.Trim(); + + private static IEverythingApi CreateApi(bool enableEverything15Support, string instanceName) + { + return enableEverything15Support + ? new EverythingApiV3(instanceName) + : new LegacyEverythingApi(); + } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs new file mode 100644 index 00000000000..3c7ed7e896a --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public interface IEverythingApi + { + ValueTask IsEverythingRunningAsync(CancellationToken token = default); + IAsyncEnumerable SearchAsync(EverythingSearchOption option, CancellationToken token = default); + Task IncrementRunCounterAsync(string fileOrFolder); + bool IsFastSortOption(EverythingSortOption sortOption); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index b73a59bcdc1..176c7eeaef4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -412,8 +412,9 @@ private static void OpenFolder(string folderPath, string fileNameOrFilePath = nu private static void IncrementEverythingRunCounterIfNeeded(string fileOrFolder) { + // What if result is not from everything or even not indexed in Everything? if (Settings.EverythingEnabled && Settings.EverythingEnableRunCount) - _ = Task.Run(() => EverythingApi.IncrementRunCounterAsync(fileOrFolder)); + _ = Task.Run(() => Settings.EverythingManagerInstance.IncrementRunCounterAsync(fileOrFolder)); } private static string GetFileMoreInfoTooltip(string filePath) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 5ecfaa7c66c..acb39b31412 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -89,7 +89,7 @@ public class Settings #region SearchEngine - private EverythingSearchManager EverythingManagerInstance => _everythingManagerInstance ??= new EverythingSearchManager(this); + internal EverythingSearchManager EverythingManagerInstance => _everythingManagerInstance ??= new EverythingSearchManager(this); private WindowsIndexSearchManager WindowsIndexSearchManager => _windowsIndexSearchManager ??= new WindowsIndexSearchManager(this); public IndexSearchEngineOption IndexSearchEngine { get; set; } = IndexSearchEngineOption.WindowsIndex; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index de28ceb9255..a5d1c4781bd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -619,7 +619,7 @@ public Visibility FastSortWarningVisibility { try { - return EverythingApi.IsFastSortOption(Settings.SortOption) ? Visibility.Collapsed : Visibility.Visible; + return Settings.EverythingManagerInstance.IsFastSortOption(Settings.SortOption) ? Visibility.Collapsed : Visibility.Visible; } catch (IPCErrorException) { @@ -642,7 +642,7 @@ public string SortOptionWarningMessage { // this method is used to determine if Everything service is running because as at Everything v1.4.1 // the sdk does not provide a dedicated interface to determine if it is running. - return EverythingApi.IsFastSortOption(Settings.SortOption) ? string.Empty + return Settings.EverythingManagerInstance.IsFastSortOption(Settings.SortOption) ? string.Empty : Localize.flowlauncher_plugin_everything_nonfastsort_warning(); } catch (IPCErrorException) @@ -678,7 +678,7 @@ public bool EnableEverything15Support var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - EverythingApi.ConfigureEverythingSupport(value, sdkDirectory, Settings.Everything15InstanceName); + Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); OnPropertyChanged(); OnPropertyChanged(nameof(FastSortWarningVisibility)); @@ -692,7 +692,7 @@ public string Everything15InstanceName set { var instanceName = string.IsNullOrWhiteSpace(value) - ? EverythingApi.DefaultEverything15InstanceName + ? EverythingApiV3.DefaultEverything15InstanceName : value.Trim(); if (Settings.Everything15InstanceName == instanceName) @@ -704,7 +704,7 @@ public string Everything15InstanceName { var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - EverythingApi.ConfigureEverythingSupport(true, sdkDirectory, instanceName); + Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); OnPropertyChanged(nameof(FastSortWarningVisibility)); OnPropertyChanged(nameof(SortOptionWarningMessage)); } From 96b666473a1bf6a83a82b67017b1bb76f992ef4a Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 11:32:36 +0800 Subject: [PATCH 15/44] Fix default everything instance name --- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index acb39b31412..eb02ec26967 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -164,7 +164,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; public bool EnableEverything15Support { get; set; } = false; - public string Everything15InstanceName { get; set; } = EverythingApi.DefaultEverything15InstanceName; + public string Everything15InstanceName { get; set; } = EverythingApiV3.DefaultEverything15InstanceName; #endregion From 4db9d67fe3697354514c7c6ba6a4f743132711ee Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 12:17:48 +0800 Subject: [PATCH 16/44] Handle the timeout result from WaitAsync(TimeSpan) before releasing the semaphore --- .../Search/Everything/EverythingAPI.cs | 56 ++++++++++++++++++- .../Search/Everything/EverythingApiV3.cs | 10 +++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 6ecd4b3d0c0..f6c57b27b17 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -169,7 +169,12 @@ private static void CheckAndThrowExceptionOnError() public async Task IncrementRunCounterAsync(string fileOrFolder) { - await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); + var _entered = await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); + if (!_entered) + { + // If we can't acquire the semaphore within the timeout, we skip incrementing the run count to avoid blocking. + return; + } try { _ = EverythingApiDllImport.Everything_IncRunCountFromFileName(fileOrFolder); @@ -179,10 +184,57 @@ public async Task IncrementRunCounterAsync(string fileOrFolder) /*ignored*/ } finally - { + { _semaphore.Release(); } } + /// + /// Convert the highlighted string from Everything API to a list of highlight indexes for our Result. + /// + /// Text inside a * quote is highlighted, two consecutive *'s is a single literal *. For example, in the highlighted text: abc*123* the 123 part is highlighted. + /// A list of zero-based character indices that should be highlighted. + public static List EverythingHighlightStringToHighlightList(string highlightString) + { + var highlightData = new List(); + + if (string.IsNullOrEmpty(highlightString)) + return highlightData; + + var isHighlighted = false; + var actualIndex = 0; // Index in the actual string (without * markers) + var length = highlightString.Length; + + for (var i = 0; i < length; i++) + { + if (highlightString[i] == '*') + { + // Check if it's a literal * (two consecutive *) + if (i + 1 < length && highlightString[i + 1] == '*') + { + // Two consecutive *'s represent a single literal * + if (isHighlighted) + { + highlightData.Add(actualIndex); + } + actualIndex++; + i++; // Skip the next * + } + else + { + isHighlighted = !isHighlighted; + } + } + else + { + // Regular character + if (isHighlighted) + { + highlightData.Add(actualIndex); + } + actualIndex++; + } + } + } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 7f42dfddf7b..22ccd42ba09 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -122,11 +122,15 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o public async Task IncrementRunCounterAsync(string fileOrFolder) { - await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); + var _entered = await _semaphore.WaitAsync(TimeSpan.FromSeconds(1)); + if (!_entered) + { + // If we can't acquire the semaphore within the timeout, we skip incrementing the run count to avoid blocking. + return; + } try { - _ = TryUseEverything3Client(client => - _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); + _ = TryUseEverything3Client(client => _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); } catch (Exception) { From 5fa18c8527929241af583629d02fef77614a6911 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 14:49:56 +0800 Subject: [PATCH 17/44] Stop dynamically loading Everything SDK --- .../Languages/en.xaml | 7 +-- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 +- .../Everything/Everything3ApiDllImport.cs | 17 ------- .../Search/Everything/EverythingAPI.cs | 48 ----------------- .../Everything/EverythingApiDllImport.cs | 18 ------- .../Everything/EverythingSearchManager.cs | 51 +++++++++---------- .../ViewModels/SettingsViewModel.cs | 7 --- 7 files changed, 28 insertions(+), 122 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index a0cd5316549..3d162b0d410 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -1,4 +1,4 @@ - @@ -44,7 +44,7 @@ Date and time format Sort Option: Everything Path: - Everything 1.5 instance name: + Everything 1.5 instance name (requires app restart): Launch Hidden Editor Path Shell Path @@ -187,7 +187,7 @@ Search Full Path Enable File/Folder Run Count - Enable Everything 1.5 support + Use Everything 1.5 (requires app restart) Click to launch or install Everything Everything Installation @@ -216,3 +216,4 @@ 1 year ago {0} years ago + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index d872ae22b1f..f23f897ee2f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -48,7 +48,7 @@ public Task InitAsync(PluginInitContext context) var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86"); - Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); + Settings.EverythingManagerInstance.InitializeApi(sdkDirectory); return Task.CompletedTask; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs index 9844330750c..5e24d7298a4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/Everything3ApiDllImport.cs @@ -26,26 +26,9 @@ public static void Load(string directory) } } - public static void Unload() - { - if (_dllHandle == IntPtr.Zero) - { - return; - } - if (!FreeLibrary(_dllHandle)) - { - throw new Win32Exception(Marshal.GetLastPInvokeError()); - } - _dllHandle = IntPtr.Zero; - } - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string name); - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool FreeLibrary(IntPtr hModule); - private const string Dll = "Everything3.dll"; [DllImport(Dll, CharSet = CharSet.Unicode)] diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index f6c57b27b17..681333f4a21 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -188,53 +188,5 @@ public async Task IncrementRunCounterAsync(string fileOrFolder) _semaphore.Release(); } } - - /// - /// Convert the highlighted string from Everything API to a list of highlight indexes for our Result. - /// - /// Text inside a * quote is highlighted, two consecutive *'s is a single literal *. For example, in the highlighted text: abc*123* the 123 part is highlighted. - /// A list of zero-based character indices that should be highlighted. - public static List EverythingHighlightStringToHighlightList(string highlightString) - { - var highlightData = new List(); - - if (string.IsNullOrEmpty(highlightString)) - return highlightData; - - var isHighlighted = false; - var actualIndex = 0; // Index in the actual string (without * markers) - var length = highlightString.Length; - - for (var i = 0; i < length; i++) - { - if (highlightString[i] == '*') - { - // Check if it's a literal * (two consecutive *) - if (i + 1 < length && highlightString[i + 1] == '*') - { - // Two consecutive *'s represent a single literal * - if (isHighlighted) - { - highlightData.Add(actualIndex); - } - actualIndex++; - i++; // Skip the next * - } - else - { - isHighlighted = !isHighlighted; - } - } - else - { - // Regular character - if (isHighlighted) - { - highlightData.Add(actualIndex); - } - actualIndex++; - } - } - } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index ad3da871993..1191c07d281 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -26,27 +26,9 @@ public static void Load(string directory) } } - public static void Unload() - { - if (_dllHandle == IntPtr.Zero) - { - return; - } - - if (!FreeLibrary(_dllHandle)) - { - throw new Win32Exception(Marshal.GetLastPInvokeError()); - } - _dllHandle = IntPtr.Zero; - } - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibrary(string name); - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool FreeLibrary(IntPtr hModule); - private const string DLL = "Everything.dll"; [DllImport(DLL, CharSet = CharSet.Unicode)] diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 7404e1a0ed5..4bdde287a1b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -13,23 +13,27 @@ public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IP { private static readonly string ClassName = nameof(EverythingSearchManager); private static readonly SemaphoreSlim _dllSemaphore = new(1, 1); - private static volatile bool _dllLoadedForSdk3 = true; private Settings Settings { get; } + private readonly bool useV3Api; + private readonly string everything15InstanceName; private readonly Lock _syncRoot = new(); - private IEverythingApi _api; + private bool isApiInitialized; + private IEverythingApi api; public EverythingSearchManager(Settings settings) { Settings = settings; - _api = CreateApi(Settings.EnableEverything15Support, GetNormalizedInstanceName(Settings.Everything15InstanceName)); + useV3Api = Settings.EnableEverything15Support; + everything15InstanceName = Settings.Everything15InstanceName; + api = CreateApi(useV3Api, GetNormalizedInstanceName(everything15InstanceName)); } private async ValueTask ThrowIfEverythingNotAvailableAsync(CancellationToken token = default) { try { - if (!await _api.IsEverythingRunningAsync(token)) + if (!await api.IsEverythingRunningAsync(token)) throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), @@ -90,7 +94,7 @@ public async IAsyncEnumerable SearchAsync(string search, [Enumerat IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in _api.SearchAsync(option, token)) + await foreach (var result in api.SearchAsync(option, token)) yield return result; } @@ -124,7 +128,7 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in _api.SearchAsync(option, token)) + await foreach (var result in api.SearchAsync(option, token)) { yield return result; } @@ -145,49 +149,40 @@ public async IAsyncEnumerable EnumerateAsync(string path, string s IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); - await foreach (var result in _api.SearchAsync(option, token)) + await foreach (var result in api.SearchAsync(option, token)) yield return result; } - public void ReloadApi(string sdkDirectory) + public void InitializeApi(string sdkDirectory) { lock (_syncRoot) { - LoadDllCore(Settings.EnableEverything15Support, sdkDirectory); - _api = CreateApi(Settings.EnableEverything15Support, GetNormalizedInstanceName(Settings.Everything15InstanceName)); + if (isApiInitialized) + return; + + LoadConfiguredDll(sdkDirectory, useV3Api); + api = CreateApi(useV3Api, GetNormalizedInstanceName(Settings.Everything15InstanceName)); + isApiInitialized = true; } } - public bool IsFastSortOption(EverythingSortOption sortOption) => _api.IsFastSortOption(sortOption); + public bool IsFastSortOption(EverythingSortOption sortOption) => api.IsFastSortOption(sortOption); - public Task IncrementRunCounterAsync(string fileOrFolder) => _api.IncrementRunCounterAsync(fileOrFolder); + public Task IncrementRunCounterAsync(string fileOrFolder) => api.IncrementRunCounterAsync(fileOrFolder); - private static void LoadDllCore(bool enableEverything15Support, string sdkDirectory) + private static void LoadConfiguredDll(string sdkDirectory, bool enableEverything15Support) { _dllSemaphore.Wait(); try { - var supportChanged = _dllLoadedForSdk3 != enableEverything15Support; - _dllLoadedForSdk3 = enableEverything15Support; - if (enableEverything15Support) { - if (supportChanged || !Everything3ApiDllImport.IsLoaded) - { - if (EverythingApiDllImport.IsLoaded) - EverythingApiDllImport.Unload(); - + if (!Everything3ApiDllImport.IsLoaded) Everything3ApiDllImport.Load(sdkDirectory); - } } else { - if (supportChanged || !EverythingApiDllImport.IsLoaded) - { - if (Everything3ApiDllImport.IsLoaded) - Everything3ApiDllImport.Unload(); - + if (!EverythingApiDllImport.IsLoaded) EverythingApiDllImport.Load(sdkDirectory); - } } } finally diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index a5d1c4781bd..cf47dfe1a32 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -676,10 +676,6 @@ public bool EnableEverything15Support Settings.EnableEverything15Support = value; - var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", - Environment.Is64BitProcess ? "x64" : "x86"); - Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); - OnPropertyChanged(); OnPropertyChanged(nameof(FastSortWarningVisibility)); OnPropertyChanged(nameof(SortOptionWarningMessage)); @@ -702,9 +698,6 @@ public string Everything15InstanceName if (EnableEverything15Support) { - var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", - Environment.Is64BitProcess ? "x64" : "x86"); - Settings.EverythingManagerInstance.ReloadApi(sdkDirectory); OnPropertyChanged(nameof(FastSortWarningVisibility)); OnPropertyChanged(nameof(SortOptionWarningMessage)); } From 7254dc0bc155b3d2a3dba49f9d2eec53adf9595b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:03:58 +0800 Subject: [PATCH 18/44] Clean code and revert useless changes --- .../Search/Everything/EverythingAPI.cs | 25 +++++++++++++------ .../Search/ResultManager.cs | 1 - 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 681333f4a21..afb940621f5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -12,10 +12,19 @@ public class LegacyEverythingApi : IEverythingApi { private const int BufferSize = 4096; private static readonly SemaphoreSlim _semaphore = new(1, 1); + // cached buffer to remove redundant allocations. private static readonly StringBuilder buffer = new(BufferSize); + const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; + const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; + + /// + /// Checks whether the sort option is Fast Sort. + /// public bool IsFastSortOption(EverythingSortOption sortOption) { + // If the Everything service is not running, then this call will incorrectly report + // the state as false. This checks for errors thrown by the api and up to the caller to handle. var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); CheckAndThrowExceptionOnError(); return fastSortOptionEnabled; @@ -43,6 +52,12 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = } } + /// + /// Searches using the specified criteria and resets the Everything API afterwards. + /// + /// The search criteria. + /// A cancellation token that stops the current search when cancellation is requested. + /// An asynchronous sequence of search results that match the specified criteria. public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) { if (option.Offset < 0) @@ -84,10 +99,8 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o builder.Append($" content:\"{option.ContentSearchKeyword}\""); } - var searchText = builder.ToString(); - EverythingApiDllImport.Everything_SetRegex(useRegex); - EverythingApiDllImport.Everything_SetSearchW(searchText); + EverythingApiDllImport.Everything_SetSearchW(builder.ToString()); EverythingApiDllImport.Everything_SetOffset(option.Offset); EverythingApiDllImport.Everything_SetMax(option.MaxCount); @@ -96,11 +109,11 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o if (option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) { - EverythingApiDllImport.Everything_SetRequestFlags(0x00000004u | 0x00000400u); + EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); } else { - EverythingApiDllImport.Everything_SetRequestFlags(0x00000004u); + EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME); } if (token.IsCancellationRequested) yield break; @@ -138,8 +151,6 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o EverythingApiDllImport.Everything_Reset(); _semaphore.Release(); } - - await Task.CompletedTask; } private static void CheckAndThrowExceptionOnError() diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index 176c7eeaef4..7845498a963 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -412,7 +412,6 @@ private static void OpenFolder(string folderPath, string fileNameOrFilePath = nu private static void IncrementEverythingRunCounterIfNeeded(string fileOrFolder) { - // What if result is not from everything or even not indexed in Everything? if (Settings.EverythingEnabled && Settings.EverythingEnableRunCount) _ = Task.Run(() => Settings.EverythingManagerInstance.IncrementRunCounterAsync(fileOrFolder)); } From 01e66975171da5316641cb0ea8d414b9e203ba59 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:14:33 +0800 Subject: [PATCH 19/44] update expected text --- .github/actions/spelling/expect.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 81b9aba97e7..fe2b8a73553 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -108,3 +108,4 @@ Msix dummyprofile browserbookmark copyurl +PInvoke From a78397d2f250a19f1e14c51d19c3c2456829c9b0 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:22:27 +0800 Subject: [PATCH 20/44] Revert unnecessary changes --- .../Search/Everything/EverythingAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index afb940621f5..d6c8fd8fbbc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -23,9 +23,9 @@ public class LegacyEverythingApi : IEverythingApi /// public bool IsFastSortOption(EverythingSortOption sortOption) { + var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); // If the Everything service is not running, then this call will incorrectly report // the state as false. This checks for errors thrown by the api and up to the caller to handle. - var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); CheckAndThrowExceptionOnError(); return fastSortOptionEnabled; } From 5a6a46163aa32805134ffb1e605e3374f7eaebef Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 29 Mar 2026 15:27:48 +0800 Subject: [PATCH 21/44] Throw error on add sort option fails --- .../Search/Everything/EverythingApiV3.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 22ccd42ba09..552358a445e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -191,10 +191,14 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c if (TryConvertSortOption(option.SortOption, out var sortPropertyId, out var ascending)) { - _ = Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending); + if (!Everything3ApiDllImport.Everything3_AddSearchSort(searchState, sortPropertyId, ascending)) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + yield break; + } } - _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); + _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); From 825674fb95f0e63292c7418178e972affac42a30 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 01:11:09 +0800 Subject: [PATCH 22/44] Move default alpha instance name to Everything Search Manager --- .../Search/Everything/EverythingApiV3.cs | 2 -- .../Search/Everything/EverythingSearchManager.cs | 3 ++- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- .../ViewModels/SettingsViewModel.cs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 552358a445e..db74746822a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -10,8 +10,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public class EverythingApiV3 : IEverythingApi { - public const string DefaultEverything15InstanceName = "1.5a"; - private const int BufferSize = 4096; private static readonly SemaphoreSlim _semaphore = new(1, 1); private static readonly StringBuilder _buffer = new(BufferSize); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 4bdde287a1b..c0277c588aa 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -20,6 +20,7 @@ public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IP private readonly Lock _syncRoot = new(); private bool isApiInitialized; private IEverythingApi api; + public const string DefaultEverything15InstanceName = "1.5a"; public EverythingSearchManager(Settings settings) { @@ -192,7 +193,7 @@ private static void LoadConfiguredDll(string sdkDirectory, bool enableEverything } private static string GetNormalizedInstanceName(string instanceName) => string.IsNullOrWhiteSpace(instanceName) - ? EverythingApiV3.DefaultEverything15InstanceName + ? DefaultEverything15InstanceName : instanceName.Trim(); private static IEverythingApi CreateApi(bool enableEverything15Support, string instanceName) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index eb02ec26967..0cd37feb478 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -164,7 +164,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; public bool EnableEverything15Support { get; set; } = false; - public string Everything15InstanceName { get; set; } = EverythingApiV3.DefaultEverything15InstanceName; + public string Everything15InstanceName { get; set; } = EverythingSearchManager.DefaultEverything15InstanceName; #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index cf47dfe1a32..a16f0bb55b8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -688,7 +688,7 @@ public string Everything15InstanceName set { var instanceName = string.IsNullOrWhiteSpace(value) - ? EverythingApiV3.DefaultEverything15InstanceName + ? EverythingSearchManager.DefaultEverything15InstanceName : value.Trim(); if (Settings.Everything15InstanceName == instanceName) From ba2e8bd8fbe2923d222e157e391595ae57d1ff61 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 13:06:21 +0800 Subject: [PATCH 23/44] Refactor EverythingSearchManager --- .../Everything-1.5-architecture-plan.md | 252 ++++++++++++++++++ .../Search/Everything/EverythingApiFactory.cs | 22 ++ .../Search/Everything/EverythingApiV3.cs | 2 +- .../EverythingAvailabilityService.cs | 68 +++++ .../Search/Everything/EverythingSdkLoader.cs | 31 +++ .../Everything/EverythingSearchManager.cs | 110 +------- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- .../ViewModels/SettingsViewModel.cs | 2 +- 8 files changed, 386 insertions(+), 103 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md b/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md new file mode 100644 index 00000000000..a0996e72cea --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md @@ -0,0 +1,252 @@ +# Everything 1.5 SDK 架构实施计划 + +本文聚焦前一轮 review 中的第 3、4、5 点: +- `EverythingSearchManager` 职责过多 +- V1/V3 搜索流程重复,容易漂移 +- V3 错误模型过于扁平 + +## 3. `EverythingSearchManager` 职责拆分计划 + +### 目标 +把当前 `EverythingSearchManager` 中的工厂、运行时初始化、可用性探测、安装引导、Provider 适配几类职责拆开,降低后续维护成本。 + +### 当前问题 +`EverythingSearchManager` 同时负责: +- 选择 `LegacyEverythingApi` / `EverythingApiV3` +- 加载 `Everything.dll` / `Everything3.dll` +- 检测 Everything 是否可连接 +- 处理“未安装/未启动”的用户提示与安装引导 +- 对外实现 `IIndexProvider` / `IContentIndexProvider` / `IPathIndexProvider` + +这会导致任何 SDK 演进都集中修改一个类。 + +### 拆分方案 + +#### 3.1 引入 `EverythingApiFactory` +职责: +- 根据设置决定创建 `LegacyEverythingApi` 还是 `EverythingApiV3` +- 统一实例名规范化逻辑 + +建议接口: +- `IEverythingApi Create(Settings settings)` + +迁移内容: +- 从 `EverythingSearchManager` 中移出: + - `CreateApi(...)` + - `GetNormalizedInstanceName(...)` + +#### 3.2 引入 `EverythingSdkLoader` +职责: +- 负责 native DLL 的一次性加载 +- 隐藏 `EverythingApiDllImport.Load(...)` / `Everything3ApiDllImport.Load(...)` 细节 +- 维护线程安全 + +建议接口: +- `void EnsureLoaded(string sdkDirectory, bool useV3Api)` + +迁移内容: +- 从 `EverythingSearchManager` 中移出: + - `_dllSemaphore` + - `LoadConfiguredDll(...)` + +#### 3.3 引入 `EverythingAvailabilityService` +职责: +- 负责“是否可用”的判定 +- 根据异常类型生成统一的可用性错误 +- 保留安装/启动引导逻辑 + +建议接口: +- `ValueTask EnsureAvailableAsync(IEverythingApi api, Settings settings, CancellationToken token = default)` + +迁移内容: +- 从 `EverythingSearchManager` 中移出: + - `ThrowIfEverythingNotAvailableAsync(...)` + - `ClickToInstallEverythingAsync(...)` + +#### 3.4 缩减 `EverythingSearchManager` +保留职责: +- 组装 `EverythingSearchOption` +- 调用 `api.SearchAsync(...)` +- 作为 Explorer 插件内的 Everything Provider 门面 + +最终效果: +- `EverythingSearchManager` 更接近应用层协调器 +- SDK、运行时、错误与 UX 引导分别归位 + +### 落地步骤 +1. 新建 `EverythingApiFactory` +2. 新建 `EverythingSdkLoader` +3. 新建 `EverythingAvailabilityService` +4. 让 `EverythingSearchManager` 通过这些组件完成现有逻辑 +5. 保持外部调用接口不变,避免影响 `Settings` / `SearchManager` + +### 验收标准 +- `EverythingSearchManager` 文件长度和私有职责显著减少 +- DLL 加载和 API 创建不再散落在 manager 中 +- 可用性判断逻辑有独立入口 +- `SearchManager` 和 UI 层无须理解 SDK 版本差异 + +--- + +## 4. V1/V3 搜索流程去重计划 + +### 目标 +提取 Everything 1.4 与 1.5 共用的查询构造和结果映射逻辑,避免双实现长期漂移。 + +### 当前重复点 +`LegacyEverythingApi.SearchAsync(...)` 与 `EverythingApiV3.SearchAsync(...)` 目前重复了以下逻辑: +- `Offset` / `MaxCount` 参数校验 +- `@` 前缀触发 regex +- 关键字、父路径、content search 的查询字符串拼接 +- 部分 cancellation 入口 +- `SearchResult` 组装思路 + +### 拆分方案 + +#### 4.1 引入 `EverythingQueryBuilder` +职责: +- 接收 `EverythingSearchOption` +- 输出标准化查询描述 + +建议输出模型: +- `SearchText` +- `UseRegex` + +建议类型: +- `EverythingPreparedQuery` +- `EverythingQueryBuilder` + +示例职责边界: +- 校验 `Offset` / `MaxCount` +- 处理 `@` 前缀 +- 构建最终 search text +- 不触碰任何 native API + +#### 4.2 引入 `EverythingResultMapper` +职责: +- 统一把 native SDK 返回值映射成 `SearchResult` +- 统一 highlight 字符串转换入口 + +说明: +- V1/V3 的底层字段读取方式不同,不强行抽象整个 native 读取过程 +- 但可把“构建 `SearchResult` 的约定”收敛起来 + +可拆分成两层: +- 共用层:`CreateResult(string fullPath, ResultType type, int score, List highlightData)` +- SDK 适配层:各自读取 full path / run count / highlight text + +#### 4.3 保留各 SDK 的最小差异面 +`LegacyEverythingApi` 保留: +- V1 专属 request flags +- `Everything_Reset()` 生命周期 +- V1 的 native 错误检查 + +`EverythingApiV3` 保留: +- search state / result list / client 生命周期 +- property request / property sort 转换 +- V3 的 native 错误检查 + +### 落地步骤 +1. 新建 `EverythingPreparedQuery` 模型 +2. 新建 `EverythingQueryBuilder` +3. 把 V1/V3 中重复的 query 构造逻辑迁移到 builder +4. 提取 `SearchResult` 组装辅助方法或 mapper +5. 保证 V1/V3 两边行为一致后,再清理重复代码 + +### 验收标准 +- `LegacyEverythingApi.SearchAsync(...)` 与 `EverythingApiV3.SearchAsync(...)` 不再各自拼接 query string +- regex 与 content search 规则只有一处定义 +- 新增搜索语法时,不需要双份修改 + +--- + +## 5. V3 错误模型细化计划 + +### 目标 +把 Everything 1.5 的“连接失败”从单一布尔值扩展为可区分的错误结果,使上层能够给出更准确的恢复策略和提示。 + +### 当前问题 +`TryConnectEverything3(out var client)` 当前只返回 `true/false`,会把以下情况混在一起: +- `Everything3.dll` 丢失 +- DLL 版本不兼容,缺少入口点 +- 实例名错误或实例不存在 +- Everything 1.5 服务未运行 +- IPC 断开 + +上层只能统一处理为“Everything 不可用”,提示粒度不足。 + +### 细化方案 + +#### 5.1 引入连接结果模型 +建议类型: +- `EverythingConnectionStatus` +- `EverythingConnectionResult` + +建议状态: +- `Success` +- `SdkMissing` +- `SdkIncompatible` +- `InstanceNotFound` +- `ServiceUnavailable` +- `Disconnected` +- `UnknownFailure` + +建议字段: +- `Status` +- `Client` +- `Exception` +- `Message`(可选) + +#### 5.2 替换 `TryConnectEverything3(...)` +当前: +- `bool TryConnectEverything3(out IntPtr client)` + +建议替换为: +- `EverythingConnectionResult ConnectEverything3()` + +收益: +- `IsEverythingRunningAsync()` 可以区分“没装 SDK”和“服务没启动” +- `IsFastSortOption(...)` 可以在实例名错误时给出更准的异常 +- `SearchAsync(...)` 可以把失败转成更合理的业务异常 + +#### 5.3 建立 V3 错误翻译层 +建议新增: +- `Everything3ErrorTranslator` + +职责: +- 解析 `Everything3_GetLastError()` +- 把 native error code 翻译成领域异常或连接状态 + +目标: +- `EverythingApiV3` 不再直接分散处理所有错误码 +- 错误语义集中定义 + +#### 5.4 上层异常映射策略 +在 `EverythingSearchManager` / 可用性服务中约定: +- `SdkMissing` / `SdkIncompatible` -> SDK 问题提示 +- `InstanceNotFound` -> 提示检查 `Everything15InstanceName` +- `ServiceUnavailable` / `Disconnected` -> 提示启动 Everything 1.5 + +### 落地步骤 +1. 新建连接状态枚举与结果模型 +2. 重写 `TryConnectEverything3(...)` 为结构化返回 +3. 新建 `Everything3ErrorTranslator` +4. 调整 `IsEverythingRunningAsync` / `SearchAsync` / `IsFastSortOption` +5. 调整上层提示逻辑,使 instance name 配置错误可被识别 + +### 验收标准 +- V3 连接失败不再只表现为 `false` +- UI 层能够区分“SDK 缺失”和“实例不可达” +- 用户配置错实例名时,得到的是针对性提示而不是泛化提示 + +--- + +## 推荐实施顺序 +1. **先做第 5 点**:先把错误模型立住,否则后续拆分职责时仍会传递模糊状态 +2. **再做第 3 点**:将连接、初始化、可用性逻辑拆出 manager +3. **最后做第 4 点**:在职责边界稳定后,再抽查询构造和结果映射,风险更低 + +## 预期收益 +- 降低 `EverythingSearchManager` 的变更面 +- 减少 V1/V3 功能演进时的不一致风险 +- 为 Everything 1.5 实例名、多实例、兼容性提示提供更稳固的基础设施 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs new file mode 100644 index 00000000000..609222dd097 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs @@ -0,0 +1,22 @@ +using System; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + internal static class EverythingApiFactory + { + internal const string DefaultEverything15InstanceName = "1.5a"; + + public static IEverythingApi Create(Settings settings) + { + ArgumentNullException.ThrowIfNull(settings); + + return settings.EnableEverything15Support + ? new EverythingApiV3(GetNormalizedInstanceName(settings.Everything15InstanceName)) + : new LegacyEverythingApi(); + } + + internal static string GetNormalizedInstanceName(string instanceName) => string.IsNullOrWhiteSpace(instanceName) + ? DefaultEverything15InstanceName + : instanceName.Trim(); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index db74746822a..0be8f7a4fec 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -308,7 +308,7 @@ private bool TryConnectEverything3(out IntPtr client) try { var normalizedInstanceName = string.IsNullOrWhiteSpace(_instanceName) - ? DefaultEverything15InstanceName + ? EverythingApiFactory.DefaultEverything15InstanceName : _instanceName.Trim(); client = Everything3ApiDllImport.Everything3_ConnectW(normalizedInstanceName); return client != IntPtr.Zero; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs new file mode 100644 index 00000000000..daf7ba9e6dc --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -0,0 +1,68 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Flow.Launcher.Plugin.Explorer.Exceptions; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + internal class EverythingAvailabilityService + { + private readonly Settings _settings; + + public EverythingAvailabilityService(Settings settings) + { + _settings = settings; + } + + public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToken token = default) + { + try + { + if (!await api.IsEverythingRunningAsync(token)) + throw new EngineNotAvailableException( + Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, + Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), + Localize.flowlauncher_plugin_everything_is_not_running(), + Constants.EverythingErrorImagePath, + ClickToInstallEverythingAsync); + } + catch (DllNotFoundException) + { + throw new EngineNotAvailableException( + Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, + "Please check whether your system is x86 or x64", + Constants.GeneralSearchErrorImagePath, + Localize.flowlauncher_plugin_everything_sdk_issue()); + } + } + + private async ValueTask ClickToInstallEverythingAsync(ActionContext _) + { + try + { + var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(_settings.EverythingInstalledPath, Main.Context.API); + + if (installedPath == null) + { + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_not_found()); + Main.Context.API.LogError(nameof(EverythingAvailabilityService), "Unable to find Everything.exe"); + + return false; + } + + _settings.EverythingInstalledPath = installedPath; + Process.Start(installedPath, "-startup"); + + return true; + } + catch (Exception e) + { + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_install_issue()); + Main.Context.API.LogException(nameof(EverythingAvailabilityService), "Failed to install Everything", e); + + return false; + } + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs new file mode 100644 index 00000000000..e36b808c07e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs @@ -0,0 +1,31 @@ +using System.Threading; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + internal static class EverythingSdkLoader + { + private static readonly SemaphoreSlim _semaphore = new(1, 1); + + public static void EnsureLoaded(string sdkDirectory, bool enableEverything15Support) + { + _semaphore.Wait(); + try + { + if (enableEverything15Support) + { + if (!Everything3ApiDllImport.IsLoaded) + Everything3ApiDllImport.Load(sdkDirectory); + } + else + { + if (!EverythingApiDllImport.IsLoaded) + EverythingApiDllImport.Load(sdkDirectory); + } + } + finally + { + _semaphore.Release(); + } + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index c0277c588aa..9e1f5a32131 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -1,6 +1,6 @@ using System; +using System; using System.Collections.Generic; -using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -11,80 +11,22 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { - private static readonly string ClassName = nameof(EverythingSearchManager); - private static readonly SemaphoreSlim _dllSemaphore = new(1, 1); - private Settings Settings { get; } - private readonly bool useV3Api; - private readonly string everything15InstanceName; + private readonly EverythingAvailabilityService _availabilityService; private readonly Lock _syncRoot = new(); private bool isApiInitialized; private IEverythingApi api; - public const string DefaultEverything15InstanceName = "1.5a"; public EverythingSearchManager(Settings settings) { Settings = settings; - useV3Api = Settings.EnableEverything15Support; - everything15InstanceName = Settings.Everything15InstanceName; - api = CreateApi(useV3Api, GetNormalizedInstanceName(everything15InstanceName)); - } - - private async ValueTask ThrowIfEverythingNotAvailableAsync(CancellationToken token = default) - { - try - { - if (!await api.IsEverythingRunningAsync(token)) - throw new EngineNotAvailableException( - Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), - Localize.flowlauncher_plugin_everything_is_not_running(), - Constants.EverythingErrorImagePath, - ClickToInstallEverythingAsync); - } - catch (DllNotFoundException) - { - throw new EngineNotAvailableException( - Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - "Please check whether your system is x86 or x64", - Constants.GeneralSearchErrorImagePath, - Localize.flowlauncher_plugin_everything_sdk_issue()); - } - } - - private async ValueTask ClickToInstallEverythingAsync(ActionContext _) - { - try - { - var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(Settings.EverythingInstalledPath, Main.Context.API); - - if (installedPath == null) - { - Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_not_found()); - Main.Context.API.LogError(ClassName, "Unable to find Everything.exe"); - - return false; - } - - Settings.EverythingInstalledPath = installedPath; - Process.Start(installedPath, "-startup"); - - return true; - } - // Sometimes Everything installation will fail because of permission issues or file not found issues - // Just let the user know that Everything is not installed properly and ask them to install it manually - catch (Exception e) - { - Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_install_issue()); - Main.Context.API.LogException(ClassName, "Failed to install Everything", e); - - return false; - } + _availabilityService = new EverythingAvailabilityService(settings); + api = EverythingApiFactory.Create(settings); } public async IAsyncEnumerable SearchAsync(string search, [EnumeratorCancellation] CancellationToken token) { - await ThrowIfEverythingNotAvailableAsync(token); + await _availabilityService.EnsureAvailableAsync(api, token); if (token.IsCancellationRequested) yield break; @@ -102,7 +44,7 @@ public async IAsyncEnumerable SearchAsync(string search, [Enumerat public async IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, [EnumeratorCancellation] CancellationToken token) { - await ThrowIfEverythingNotAvailableAsync(token); + await _availabilityService.EnsureAvailableAsync(api, token); if (!Settings.EnableEverythingContentSearch) { @@ -137,7 +79,7 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc public async IAsyncEnumerable EnumerateAsync(string path, string search, bool recursive, [EnumeratorCancellation] CancellationToken token) { - await ThrowIfEverythingNotAvailableAsync(token); + await _availabilityService.EnsureAvailableAsync(api, token); if (token.IsCancellationRequested) yield break; @@ -153,6 +95,7 @@ public async IAsyncEnumerable EnumerateAsync(string path, string s await foreach (var result in api.SearchAsync(option, token)) yield return result; } + public void InitializeApi(string sdkDirectory) { lock (_syncRoot) @@ -160,8 +103,8 @@ public void InitializeApi(string sdkDirectory) if (isApiInitialized) return; - LoadConfiguredDll(sdkDirectory, useV3Api); - api = CreateApi(useV3Api, GetNormalizedInstanceName(Settings.Everything15InstanceName)); + EverythingSdkLoader.EnsureLoaded(sdkDirectory, Settings.EnableEverything15Support); + api = EverythingApiFactory.Create(Settings); isApiInitialized = true; } } @@ -169,38 +112,5 @@ public void InitializeApi(string sdkDirectory) public bool IsFastSortOption(EverythingSortOption sortOption) => api.IsFastSortOption(sortOption); public Task IncrementRunCounterAsync(string fileOrFolder) => api.IncrementRunCounterAsync(fileOrFolder); - - private static void LoadConfiguredDll(string sdkDirectory, bool enableEverything15Support) - { - _dllSemaphore.Wait(); - try - { - if (enableEverything15Support) - { - if (!Everything3ApiDllImport.IsLoaded) - Everything3ApiDllImport.Load(sdkDirectory); - } - else - { - if (!EverythingApiDllImport.IsLoaded) - EverythingApiDllImport.Load(sdkDirectory); - } - } - finally - { - _dllSemaphore.Release(); - } - } - - private static string GetNormalizedInstanceName(string instanceName) => string.IsNullOrWhiteSpace(instanceName) - ? DefaultEverything15InstanceName - : instanceName.Trim(); - - private static IEverythingApi CreateApi(bool enableEverything15Support, string instanceName) - { - return enableEverything15Support - ? new EverythingApiV3(instanceName) - : new LegacyEverythingApi(); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 0cd37feb478..e746bc453e6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -164,7 +164,7 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; public bool EnableEverything15Support { get; set; } = false; - public string Everything15InstanceName { get; set; } = EverythingSearchManager.DefaultEverything15InstanceName; + public string Everything15InstanceName { get; set; } = EverythingApiFactory.DefaultEverything15InstanceName; #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index a16f0bb55b8..7f0d2298252 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -688,7 +688,7 @@ public string Everything15InstanceName set { var instanceName = string.IsNullOrWhiteSpace(value) - ? EverythingSearchManager.DefaultEverything15InstanceName + ? EverythingApiFactory.DefaultEverything15InstanceName : value.Trim(); if (Settings.Everything15InstanceName == instanceName) From ca3cb6eb6319074ed3b584df4fb8f7f9a7c2e7a8 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 17:33:46 +0800 Subject: [PATCH 24/44] Extract commone code in API --- .../Search/Everything/EverythingAPI.cs | 58 ++++++----------- .../Search/Everything/EverythingApiV3.cs | 40 +++--------- .../Search/Everything/EverythingHelper.cs | 64 ++++++++++++++++--- .../Everything/EverythingSearchOption.cs | 3 +- 4 files changed, 82 insertions(+), 83 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index d6c8fd8fbbc..7d3030c058b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -44,7 +44,7 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = try { _ = EverythingApiDllImport.Everything_GetMajorVersion(); - return EverythingApiDllImport.Everything_GetLastError() != EverythingHelper.StateCode.IPCError; + return EverythingApiDllImport.Everything_GetLastError() != EverythingStateCode.IPCError; } finally { @@ -60,10 +60,8 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = /// An asynchronous sequence of search results that match the specified criteria. public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) { - if (option.Offset < 0) - throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); - if (option.MaxCount < 0) - throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); + var query = EverythingHelper.PrepareQuery(option); + var preparedOption = query.Option; try { @@ -79,35 +77,15 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o if (token.IsCancellationRequested) yield break; - var useRegex = false; - if (option.Keyword.StartsWith("@")) - { - useRegex = true; - option.Keyword = option.Keyword[1..]; - } - - var builder = new StringBuilder(); - builder.Append(option.Keyword); - - if (!string.IsNullOrWhiteSpace(option.ParentPath)) - { - builder.Append($" {(option.IsRecursive ? "" : "parent:")}\"{option.ParentPath}\""); - } - - if (option.IsContentSearch) - { - builder.Append($" content:\"{option.ContentSearchKeyword}\""); - } - - EverythingApiDllImport.Everything_SetRegex(useRegex); - EverythingApiDllImport.Everything_SetSearchW(builder.ToString()); - EverythingApiDllImport.Everything_SetOffset(option.Offset); - EverythingApiDllImport.Everything_SetMax(option.MaxCount); + EverythingApiDllImport.Everything_SetRegex(preparedOption.UseRegex); + EverythingApiDllImport.Everything_SetSearchW(query.SearchText); + EverythingApiDllImport.Everything_SetOffset(preparedOption.Offset); + EverythingApiDllImport.Everything_SetMax(preparedOption.MaxCount); - EverythingApiDllImport.Everything_SetSort(option.SortOption); - EverythingApiDllImport.Everything_SetMatchPath(option.IsFullPathSearch); + EverythingApiDllImport.Everything_SetSort(preparedOption.SortOption); + EverythingApiDllImport.Everything_SetMatchPath(preparedOption.IsFullPathSearch); - if (option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) + if (preparedOption.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) { EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); } @@ -157,21 +135,21 @@ private static void CheckAndThrowExceptionOnError() { switch (EverythingApiDllImport.Everything_GetLastError()) { - case EverythingHelper.StateCode.CreateThreadError: + case EverythingStateCode.CreateThreadError: throw new CreateThreadException(); - case EverythingHelper.StateCode.CreateWindowError: + case EverythingStateCode.CreateWindowError: throw new CreateWindowException(); - case EverythingHelper.StateCode.InvalidCallError: + case EverythingStateCode.InvalidCallError: throw new InvalidCallException(); - case EverythingHelper.StateCode.InvalidIndexError: + case EverythingStateCode.InvalidIndexError: throw new InvalidIndexException(); - case EverythingHelper.StateCode.IPCError: + case EverythingStateCode.IPCError: throw new IPCErrorException(); - case EverythingHelper.StateCode.MemoryError: + case EverythingStateCode.MemoryError: throw new MemoryErrorException(); - case EverythingHelper.StateCode.RegisterClassExError: + case EverythingStateCode.RegisterClassExError: throw new RegisterClassExException(); - case EverythingHelper.StateCode.OK: + case EverythingStateCode.OK: break; default: throw new ArgumentOutOfRangeException(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 0be8f7a4fec..e4fbdf44805 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -65,10 +65,8 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) { - if (option.Offset < 0) - throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); - if (option.MaxCount < 0) - throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); + var query = EverythingHelper.PrepareQuery(option); + var preparedOption = query.Option; try { @@ -84,32 +82,10 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o if (token.IsCancellationRequested) yield break; - var useRegex = false; - if (option.Keyword.StartsWith("@")) - { - useRegex = true; - option.Keyword = option.Keyword[1..]; - } - - var builder = new StringBuilder(); - builder.Append(option.Keyword); - - if (!string.IsNullOrWhiteSpace(option.ParentPath)) - { - builder.Append($" {(option.IsRecursive ? "" : "parent:")}\"{option.ParentPath}\""); - } - - if (option.IsContentSearch) - { - builder.Append($" content:\"{option.ContentSearchKeyword}\""); - } - - var searchText = builder.ToString(); - if (!TryConnectEverything3(out var client)) throw new IPCErrorException(); - await foreach (var result in SearchWithEverything3Async(client, option, searchText, useRegex, token)) + await foreach (var result in SearchWithEverything3Async(client, preparedOption, query, token)) yield return result; } finally @@ -165,8 +141,7 @@ public bool IsFastSortOption(EverythingSortOption sortOption) private async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, EverythingSearchOption option, - string searchText, - bool useRegex, + EverythingHelper.PreparedQuery query, [EnumeratorCancellation] CancellationToken token) { IntPtr searchState = IntPtr.Zero; @@ -180,9 +155,9 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c yield break; } - _ = Everything3ApiDllImport.Everything3_SetSearchRegex(searchState, useRegex); + _ = Everything3ApiDllImport.Everything3_SetSearchRegex(searchState, option.UseRegex); _ = Everything3ApiDllImport.Everything3_SetSearchMatchPath(searchState, option.IsFullPathSearch); - _ = Everything3ApiDllImport.Everything3_SetSearchTextW(searchState, searchText); + _ = Everything3ApiDllImport.Everything3_SetSearchTextW(searchState, query.SearchText); _ = Everything3ApiDllImport.Everything3_SetSearchHideResultOmissions(searchState, true); _ = Everything3ApiDllImport.Everything3_SetSearchViewportOffset(searchState, (nuint)option.Offset); _ = Everything3ApiDllImport.Everything3_SetSearchViewportCount(searchState, (nuint)option.MaxCount); @@ -242,7 +217,8 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) ? ResultType.Volume : ResultType.File, - Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)) + Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)), + HighlightData = [] }; if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs index 8f8db86b5c6..0be29b4ab57 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs @@ -1,21 +1,63 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Text; namespace Flow.Launcher.Plugin.Explorer.Search.Everything { + public enum EverythingStateCode + { + OK, + MemoryError, + IPCError, + RegisterClassExError, + CreateWindowError, + CreateThreadError, + InvalidIndexError, + InvalidCallError + } + public static class EverythingHelper { - public enum StateCode + #region Query + + public readonly record struct PreparedQuery( + EverythingSearchOption Option, + string SearchText); + + public static PreparedQuery PrepareQuery(EverythingSearchOption option) { - OK, - MemoryError, - IPCError, - RegisterClassExError, - CreateWindowError, - CreateThreadError, - InvalidIndexError, - InvalidCallError + if (option.Offset < 0) + throw new ArgumentOutOfRangeException(nameof(option.Offset), option.Offset, "Offset must be greater than or equal to 0"); + if (option.MaxCount < 0) + throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); + + var keyword = option.Keyword; + if (!string.IsNullOrEmpty(keyword) && keyword.StartsWith("@", StringComparison.Ordinal)) + { + option.UseRegex = true; + keyword = keyword[1..]; + } + + var builder = new StringBuilder(); + builder.Append(keyword); + + if (!string.IsNullOrWhiteSpace(option.ParentPath)) + { + builder.Append($" {(option.IsRecursive ? "" : "parent:")}\"{option.ParentPath}\""); + } + + if (option.IsContentSearch) + { + builder.Append($" content:\"{option.ContentSearchKeyword}\""); + } + + return new PreparedQuery(option with { Keyword = keyword }, builder.ToString()); } + #endregion + + #region Result + /// /// Convert the highlighted string from Everything API to a list of highlight indexes for our Result. /// @@ -65,5 +107,7 @@ public static List EverythingHighlightStringToHighlightList(string highligh return highlightData; } + + #endregion } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs index d8b670a0895..1d6446d396a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs @@ -10,6 +10,7 @@ public record struct EverythingSearchOption( int Offset = 0, int MaxCount = 100, bool IsFullPathSearch = true, - bool IsRunCounterEnabled = true + bool IsRunCounterEnabled = true, + bool UseRegex = false ); } From cfdff0de03f8fa96355d846ddc292343dce4b3b6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 18:00:49 +0800 Subject: [PATCH 25/44] Extract methods of API v3 --- .../Everything/EverythingApiDllImport.cs | 2 +- .../Search/Everything/EverythingApiV3.cs | 109 ++++++++++-------- .../Everything/EverythingSearchManager.cs | 1 - 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index 1191c07d281..9f2a5b739bc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -74,7 +74,7 @@ public static void Load(string directory) internal static extern string Everything_GetSearchW(); [DllImport(DLL)] - internal static extern EverythingHelper.StateCode Everything_GetLastError(); + internal static extern EverythingStateCode Everything_GetLastError(); [DllImport(DLL, CharSet = CharSet.Unicode)] internal static extern bool Everything_QueryW(bool bWait); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index e4fbdf44805..4e7d7df5618 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -139,7 +139,7 @@ public bool IsFastSortOption(EverythingSortOption sortOption) return true; } - private async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, + private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, EverythingSearchOption option, EverythingHelper.PreparedQuery query, [EnumeratorCancellation] CancellationToken token) @@ -171,7 +171,7 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c } } - _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); + _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); @@ -195,54 +195,8 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c yield break; } - _buffer.Clear(); - var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, idx, _buffer, BufferSize); - if (fullPathLength == 0) - { - CheckAndThrowExceptionOnErrorFromEverything3(); + if (!TryCreateSearchResult(resultList, idx, out var result)) continue; - } - - var fullPath = _buffer.ToString(); - if (string.IsNullOrEmpty(fullPath)) - { - continue; - } - - var result = new SearchResult - { - FullPath = fullPath, - Type = Everything3ApiDllImport.Everything3_IsFolderResult(resultList, idx) - ? ResultType.Folder - : Everything3ApiDllImport.Everything3_IsRootResult(resultList, idx) - ? ResultType.Volume - : ResultType.File, - Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, idx)), - HighlightData = [] - }; - - if (Everything3ApiDllImport.Everything3_GetSearchPropertyRequestHighlight(searchState, 0)) - { - _buffer.Clear(); - var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( - resultList, - idx, - EVERYTHING3_PROPERTY_ID_NAME, - _buffer, - BufferSize); - - if (highlightedFileNameLength > 0) - { - var highlightData = EverythingHelper.EverythingHighlightStringToHighlightList(_buffer.ToString()); - if (highlightData.Count > 0) - { - result = result with - { - HighlightData = highlightData - }; - } - } - } yield return result; } @@ -261,6 +215,63 @@ private async IAsyncEnumerable SearchWithEverything3Async(IntPtr c await Task.CompletedTask; } + private static bool TryCreateSearchResult(IntPtr resultList, nuint resultIndex, out SearchResult result) + { + result = default; + + if (!TryGetResultFullPath(resultList, resultIndex, out var fullPath)) + return false; + + result = new SearchResult + { + FullPath = fullPath, + Type = GetResultType(resultList, resultIndex), + Score = Convert.ToInt32(Everything3ApiDllImport.Everything3_GetResultRunCount(resultList, resultIndex)), + HighlightData = GetHighlightData(resultList, resultIndex) + }; + + return true; + } + + private static bool TryGetResultFullPath(IntPtr resultList, nuint resultIndex, out string fullPath) + { + _buffer.Clear(); + var fullPathLength = Everything3ApiDllImport.Everything3_GetResultFullPathNameW(resultList, resultIndex, _buffer, BufferSize); + if (fullPathLength == 0) + { + CheckAndThrowExceptionOnErrorFromEverything3(); + fullPath = string.Empty; + return false; + } + + fullPath = _buffer.ToString(); + return !string.IsNullOrEmpty(fullPath); + } + + private static ResultType GetResultType(IntPtr resultList, nuint resultIndex) + { + return Everything3ApiDllImport.Everything3_IsFolderResult(resultList, resultIndex) + ? ResultType.Folder + : Everything3ApiDllImport.Everything3_IsRootResult(resultList, resultIndex) + ? ResultType.Volume + : ResultType.File; + } + + private static List GetHighlightData(IntPtr resultList, nuint resultIndex) + { + _buffer.Clear(); + var highlightedFileNameLength = Everything3ApiDllImport.Everything3_GetResultPropertyTextHighlightedW( + resultList, + resultIndex, + EVERYTHING3_PROPERTY_ID_NAME, + _buffer, + BufferSize); + + return highlightedFileNameLength > 0 + ? EverythingHelper.EverythingHighlightStringToHighlightList(_buffer.ToString()) + : []; + } + private bool TryUseEverything3Client(Action action) { if (!TryConnectEverything3(out var client)) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 9e1f5a32131..787b5e3bb40 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -1,5 +1,4 @@ using System; -using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; From f439a6d3e9efa51c822fb5dd9ccdd45b21bb6eef Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 18:53:42 +0800 Subject: [PATCH 26/44] Update exceptions check --- .../Languages/en.xaml | 1 + .../Search/Everything/EverythingApiV3.cs | 18 +++++++++++++----- .../EverythingAvailabilityService.cs | 4 ++-- .../ViewModels/SettingsViewModel.cs | 4 ++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 3d162b0d410..557aaf46976 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -152,6 +152,7 @@ Failed to load Everything SDK + Please check whether your system is x86 or x64 Warning: Everything service is not running Error while querying Everything Sort By diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 4e7d7df5618..37d65448cff 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -55,7 +55,11 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = try { - return TryUseEverything3Client(static _ => { }); + if (!TryConnectEverything3(out var client)) + return false; + + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + return true; } finally { @@ -104,7 +108,8 @@ public async Task IncrementRunCounterAsync(string fileOrFolder) } try { - _ = TryUseEverything3Client(client => _ = Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder)); + if (TryConnectEverything3(out var client)) + Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder); } catch (Exception) { @@ -291,12 +296,12 @@ private bool TryUseEverything3Client(Action action) private bool TryConnectEverything3(out IntPtr client) { client = IntPtr.Zero; + var normalizedInstanceName = string.IsNullOrWhiteSpace(_instanceName) + ? EverythingApiFactory.DefaultEverything15InstanceName + : _instanceName.Trim(); try { - var normalizedInstanceName = string.IsNullOrWhiteSpace(_instanceName) - ? EverythingApiFactory.DefaultEverything15InstanceName - : _instanceName.Trim(); client = Everything3ApiDllImport.Everything3_ConnectW(normalizedInstanceName); return client != IntPtr.Zero; } @@ -310,6 +315,9 @@ private bool TryConnectEverything3(out IntPtr client) } } + /// + /// Covert the old Everything 1.4 sort options in our UI to Everything 3 property ID and sort direction for compatibility. + /// private static bool TryConvertSortOption(EverythingSortOption sortOption, out uint propertyId, out bool ascending) { switch (sortOption) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs index daf7ba9e6dc..de497861000 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -27,11 +27,11 @@ public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToke Constants.EverythingErrorImagePath, ClickToInstallEverythingAsync); } - catch (DllNotFoundException) + catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) { throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - "Please check whether your system is x86 or x64", + Localize.flowlauncher_plugin_everything_architecture_check(), Constants.GeneralSearchErrorImagePath, Localize.flowlauncher_plugin_everything_sdk_issue()); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 7f0d2298252..601f74170e4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -627,7 +627,7 @@ public Visibility FastSortWarningVisibility // update the message to let user know in the settings panel. return Visibility.Visible; } - catch (DllNotFoundException) + catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) { return Visibility.Collapsed; } @@ -649,7 +649,7 @@ public string SortOptionWarningMessage { return Localize.flowlauncher_plugin_everything_is_not_running(); } - catch (DllNotFoundException) + catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) { return Localize.flowlauncher_plugin_everything_sdk_issue(); } From 6811cdd157ce3b35265dc591246214d418355877 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 18:58:06 +0800 Subject: [PATCH 27/44] Delete Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md --- .../Everything-1.5-architecture-plan.md | 252 ------------------ 1 file changed, 252 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md b/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md deleted file mode 100644 index a0996e72cea..00000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Everything-1.5-architecture-plan.md +++ /dev/null @@ -1,252 +0,0 @@ -# Everything 1.5 SDK 架构实施计划 - -本文聚焦前一轮 review 中的第 3、4、5 点: -- `EverythingSearchManager` 职责过多 -- V1/V3 搜索流程重复,容易漂移 -- V3 错误模型过于扁平 - -## 3. `EverythingSearchManager` 职责拆分计划 - -### 目标 -把当前 `EverythingSearchManager` 中的工厂、运行时初始化、可用性探测、安装引导、Provider 适配几类职责拆开,降低后续维护成本。 - -### 当前问题 -`EverythingSearchManager` 同时负责: -- 选择 `LegacyEverythingApi` / `EverythingApiV3` -- 加载 `Everything.dll` / `Everything3.dll` -- 检测 Everything 是否可连接 -- 处理“未安装/未启动”的用户提示与安装引导 -- 对外实现 `IIndexProvider` / `IContentIndexProvider` / `IPathIndexProvider` - -这会导致任何 SDK 演进都集中修改一个类。 - -### 拆分方案 - -#### 3.1 引入 `EverythingApiFactory` -职责: -- 根据设置决定创建 `LegacyEverythingApi` 还是 `EverythingApiV3` -- 统一实例名规范化逻辑 - -建议接口: -- `IEverythingApi Create(Settings settings)` - -迁移内容: -- 从 `EverythingSearchManager` 中移出: - - `CreateApi(...)` - - `GetNormalizedInstanceName(...)` - -#### 3.2 引入 `EverythingSdkLoader` -职责: -- 负责 native DLL 的一次性加载 -- 隐藏 `EverythingApiDllImport.Load(...)` / `Everything3ApiDllImport.Load(...)` 细节 -- 维护线程安全 - -建议接口: -- `void EnsureLoaded(string sdkDirectory, bool useV3Api)` - -迁移内容: -- 从 `EverythingSearchManager` 中移出: - - `_dllSemaphore` - - `LoadConfiguredDll(...)` - -#### 3.3 引入 `EverythingAvailabilityService` -职责: -- 负责“是否可用”的判定 -- 根据异常类型生成统一的可用性错误 -- 保留安装/启动引导逻辑 - -建议接口: -- `ValueTask EnsureAvailableAsync(IEverythingApi api, Settings settings, CancellationToken token = default)` - -迁移内容: -- 从 `EverythingSearchManager` 中移出: - - `ThrowIfEverythingNotAvailableAsync(...)` - - `ClickToInstallEverythingAsync(...)` - -#### 3.4 缩减 `EverythingSearchManager` -保留职责: -- 组装 `EverythingSearchOption` -- 调用 `api.SearchAsync(...)` -- 作为 Explorer 插件内的 Everything Provider 门面 - -最终效果: -- `EverythingSearchManager` 更接近应用层协调器 -- SDK、运行时、错误与 UX 引导分别归位 - -### 落地步骤 -1. 新建 `EverythingApiFactory` -2. 新建 `EverythingSdkLoader` -3. 新建 `EverythingAvailabilityService` -4. 让 `EverythingSearchManager` 通过这些组件完成现有逻辑 -5. 保持外部调用接口不变,避免影响 `Settings` / `SearchManager` - -### 验收标准 -- `EverythingSearchManager` 文件长度和私有职责显著减少 -- DLL 加载和 API 创建不再散落在 manager 中 -- 可用性判断逻辑有独立入口 -- `SearchManager` 和 UI 层无须理解 SDK 版本差异 - ---- - -## 4. V1/V3 搜索流程去重计划 - -### 目标 -提取 Everything 1.4 与 1.5 共用的查询构造和结果映射逻辑,避免双实现长期漂移。 - -### 当前重复点 -`LegacyEverythingApi.SearchAsync(...)` 与 `EverythingApiV3.SearchAsync(...)` 目前重复了以下逻辑: -- `Offset` / `MaxCount` 参数校验 -- `@` 前缀触发 regex -- 关键字、父路径、content search 的查询字符串拼接 -- 部分 cancellation 入口 -- `SearchResult` 组装思路 - -### 拆分方案 - -#### 4.1 引入 `EverythingQueryBuilder` -职责: -- 接收 `EverythingSearchOption` -- 输出标准化查询描述 - -建议输出模型: -- `SearchText` -- `UseRegex` - -建议类型: -- `EverythingPreparedQuery` -- `EverythingQueryBuilder` - -示例职责边界: -- 校验 `Offset` / `MaxCount` -- 处理 `@` 前缀 -- 构建最终 search text -- 不触碰任何 native API - -#### 4.2 引入 `EverythingResultMapper` -职责: -- 统一把 native SDK 返回值映射成 `SearchResult` -- 统一 highlight 字符串转换入口 - -说明: -- V1/V3 的底层字段读取方式不同,不强行抽象整个 native 读取过程 -- 但可把“构建 `SearchResult` 的约定”收敛起来 - -可拆分成两层: -- 共用层:`CreateResult(string fullPath, ResultType type, int score, List highlightData)` -- SDK 适配层:各自读取 full path / run count / highlight text - -#### 4.3 保留各 SDK 的最小差异面 -`LegacyEverythingApi` 保留: -- V1 专属 request flags -- `Everything_Reset()` 生命周期 -- V1 的 native 错误检查 - -`EverythingApiV3` 保留: -- search state / result list / client 生命周期 -- property request / property sort 转换 -- V3 的 native 错误检查 - -### 落地步骤 -1. 新建 `EverythingPreparedQuery` 模型 -2. 新建 `EverythingQueryBuilder` -3. 把 V1/V3 中重复的 query 构造逻辑迁移到 builder -4. 提取 `SearchResult` 组装辅助方法或 mapper -5. 保证 V1/V3 两边行为一致后,再清理重复代码 - -### 验收标准 -- `LegacyEverythingApi.SearchAsync(...)` 与 `EverythingApiV3.SearchAsync(...)` 不再各自拼接 query string -- regex 与 content search 规则只有一处定义 -- 新增搜索语法时,不需要双份修改 - ---- - -## 5. V3 错误模型细化计划 - -### 目标 -把 Everything 1.5 的“连接失败”从单一布尔值扩展为可区分的错误结果,使上层能够给出更准确的恢复策略和提示。 - -### 当前问题 -`TryConnectEverything3(out var client)` 当前只返回 `true/false`,会把以下情况混在一起: -- `Everything3.dll` 丢失 -- DLL 版本不兼容,缺少入口点 -- 实例名错误或实例不存在 -- Everything 1.5 服务未运行 -- IPC 断开 - -上层只能统一处理为“Everything 不可用”,提示粒度不足。 - -### 细化方案 - -#### 5.1 引入连接结果模型 -建议类型: -- `EverythingConnectionStatus` -- `EverythingConnectionResult` - -建议状态: -- `Success` -- `SdkMissing` -- `SdkIncompatible` -- `InstanceNotFound` -- `ServiceUnavailable` -- `Disconnected` -- `UnknownFailure` - -建议字段: -- `Status` -- `Client` -- `Exception` -- `Message`(可选) - -#### 5.2 替换 `TryConnectEverything3(...)` -当前: -- `bool TryConnectEverything3(out IntPtr client)` - -建议替换为: -- `EverythingConnectionResult ConnectEverything3()` - -收益: -- `IsEverythingRunningAsync()` 可以区分“没装 SDK”和“服务没启动” -- `IsFastSortOption(...)` 可以在实例名错误时给出更准的异常 -- `SearchAsync(...)` 可以把失败转成更合理的业务异常 - -#### 5.3 建立 V3 错误翻译层 -建议新增: -- `Everything3ErrorTranslator` - -职责: -- 解析 `Everything3_GetLastError()` -- 把 native error code 翻译成领域异常或连接状态 - -目标: -- `EverythingApiV3` 不再直接分散处理所有错误码 -- 错误语义集中定义 - -#### 5.4 上层异常映射策略 -在 `EverythingSearchManager` / 可用性服务中约定: -- `SdkMissing` / `SdkIncompatible` -> SDK 问题提示 -- `InstanceNotFound` -> 提示检查 `Everything15InstanceName` -- `ServiceUnavailable` / `Disconnected` -> 提示启动 Everything 1.5 - -### 落地步骤 -1. 新建连接状态枚举与结果模型 -2. 重写 `TryConnectEverything3(...)` 为结构化返回 -3. 新建 `Everything3ErrorTranslator` -4. 调整 `IsEverythingRunningAsync` / `SearchAsync` / `IsFastSortOption` -5. 调整上层提示逻辑,使 instance name 配置错误可被识别 - -### 验收标准 -- V3 连接失败不再只表现为 `false` -- UI 层能够区分“SDK 缺失”和“实例不可达” -- 用户配置错实例名时,得到的是针对性提示而不是泛化提示 - ---- - -## 推荐实施顺序 -1. **先做第 5 点**:先把错误模型立住,否则后续拆分职责时仍会传递模糊状态 -2. **再做第 3 点**:将连接、初始化、可用性逻辑拆出 manager -3. **最后做第 4 点**:在职责边界稳定后,再抽查询构造和结果映射,风险更低 - -## 预期收益 -- 降低 `EverythingSearchManager` 的变更面 -- 减少 V1/V3 功能演进时的不一致风险 -- 为 Everything 1.5 实例名、多实例、兼容性提示提供更稳固的基础设施 From e21f300c1ae61bea21798b19582c6e3730125445 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:04:42 +0800 Subject: [PATCH 28/44] Destroy the Everything3 client after incrementing run count Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --- .../Search/Everything/EverythingApiV3.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 37d65448cff..b7c1e932e71 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -109,7 +109,16 @@ public async Task IncrementRunCounterAsync(string fileOrFolder) try { if (TryConnectEverything3(out var client)) - Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder); + { + try + { + Everything3ApiDllImport.Everything3_IncRunCountFromFilenameW(client, fileOrFolder); + } + finally + { + _ = Everything3ApiDllImport.Everything3_DestroyClient(client); + } + } } catch (Exception) { From ae6720b7c474c4c7352a71106080ec3d162d3159 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 5 Apr 2026 18:26:54 +0800 Subject: [PATCH 29/44] Update exceptional message --- .../Languages/en.xaml | 3 +++ .../EverythingAvailabilityService.cs | 18 ++++++++++++++++-- .../ViewModels/SettingsViewModel.cs | 4 +++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 557aaf46976..af9d61177ea 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -154,6 +154,9 @@ Failed to load Everything SDK Please check whether your system is x86 or x64 Warning: Everything service is not running + Warning: Everything 1.5 is unavailable + Ensure Everything is running and verify the configured instance name + Warning: Everything 1.5 is unavailable. The service may not be running, or the instance name may be invalid Error while querying Everything Sort By Name ↑ diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs index de497861000..dbde7ff3093 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -20,12 +20,26 @@ public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToke try { if (!await api.IsEverythingRunningAsync(token)) - throw new EngineNotAvailableException( + { + if (_settings.EnableEverything15Support) + { + throw new EngineNotAvailableException( + Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, + Localize.flowlauncher_plugin_everything_15_resolution(), + Localize.flowlauncher_plugin_everything_15_unavailable(), + Constants.EverythingErrorImagePath, + ClickToInstallEverythingAsync); + } + else + { + throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), - Localize.flowlauncher_plugin_everything_is_not_running(), + Localize.flowlauncher_plugin_everything_15_unavailable(), Constants.EverythingErrorImagePath, ClickToInstallEverythingAsync); + } + } } catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 601f74170e4..22093a9abf1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -647,7 +647,9 @@ public string SortOptionWarningMessage } catch (IPCErrorException) { - return Localize.flowlauncher_plugin_everything_is_not_running(); + return Settings.EnableEverything15Support + ? Localize.flowlauncher_plugin_everything_15_sort_warning() + : Localize.flowlauncher_plugin_everything_is_not_running(); } catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) { From d267f3fd8c09dd650fea51c87ae0099b7b479c1c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 3 May 2026 14:20:57 +0800 Subject: [PATCH 30/44] Remove x86 Everything dll --- .../EverythingSDK/x86/Everything.dll | Bin 85320 -> 0 bytes .../EverythingSDK/x86/Everything3.dll | Bin 111272 -> 0 bytes .../Flow.Launcher.Plugin.Explorer.csproj | 8 +------- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 3 +-- 4 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything.dll delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything3.dll diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything.dll b/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything.dll deleted file mode 100644 index de73b87d109a74e490b57434abc5f413906152aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85320 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 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything3.dll b/Plugins/Flow.Launcher.Plugin.Explorer/EverythingSDK/x86/Everything3.dll deleted file mode 100644 index 3d2659ada522357eb73759ec4840690430b56ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111272 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 + Library @@ -29,15 +29,9 @@ PreserveNewest - - PreserveNewest - PreserveNewest - - PreserveNewest - diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index f23f897ee2f..958d3a54481 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -46,8 +46,7 @@ public Task InitAsync(PluginInitContext context) searchManager = new SearchManager(Settings, Context); ResultManager.Init(Context, Settings); - var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", - Environment.Is64BitProcess ? "x64" : "x86"); + var sdkDirectory = Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", "x64"); Settings.EverythingManagerInstance.InitializeApi(sdkDirectory); return Task.CompletedTask; } From f0730e244903bb95f5fda8a5b5ae5c88dff237ae Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 3 May 2026 14:56:31 +0800 Subject: [PATCH 31/44] Fix unsync variable status --- .../Search/Everything/EverythingAvailabilityService.cs | 2 +- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 ++ .../ViewModels/SettingsViewModel.cs | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs index dbde7ff3093..565846e214c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -21,7 +21,7 @@ public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToke { if (!await api.IsEverythingRunningAsync(token)) { - if (_settings.EnableEverything15Support) + if (api is EverythingApiV3) { throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index e746bc453e6..00ee337ab2e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -163,6 +163,8 @@ public enum ContentIndexSearchEngineOption public bool EverythingSearchFullPath { get; set; } = false; public bool EverythingEnableRunCount { get; set; } = true; + + // This is only used as a flag to determine whether to show the Everything 1.5 support option in the settings UI, and to determine which instance of Everything API to initialize in the EverythingSearchManager. public bool EnableEverything15Support { get; set; } = false; public string Everything15InstanceName { get; set; } = EverythingApiFactory.DefaultEverything15InstanceName; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 22093a9abf1..31254863868 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -28,11 +28,14 @@ public partial class SettingsViewModel : BaseModel public IReadOnlyList> ContentIndexSearchEngines { get; set; } public IReadOnlyList> PathEnumerationEngines { get; set; } + // Cache when initializing + private readonly bool UsingEverything15; + public SettingsViewModel(PluginInitContext context, Settings settings) { Context = context; Settings = settings; - + UsingEverything15 = settings.EnableEverything15Support; InitializeEngineSelection(); InitializeActionKeywordModels(); } @@ -647,7 +650,7 @@ public string SortOptionWarningMessage } catch (IPCErrorException) { - return Settings.EnableEverything15Support + return UsingEverything15 ? Localize.flowlauncher_plugin_everything_15_sort_warning() : Localize.flowlauncher_plugin_everything_is_not_running(); } From cfd540b742fbd74662924c73daf1c1719f84ee33 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 3 May 2026 20:19:30 +0800 Subject: [PATCH 32/44] Fix missing option --- .../Search/Everything/EverythingApiV3.cs | 7 +++++-- .../Search/Everything/EverythingSortOption.cs | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index b7c1e932e71..ead5ea09c1b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -160,6 +160,8 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I { IntPtr searchState = IntPtr.Zero; IntPtr resultList = IntPtr.Zero; + var includeRunCount = option.IsRunCounterEnabled || option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING || option.SortOption == EverythingSortOption.RUN_COUNT_ASCENDING; + try { searchState = Everything3ApiDllImport.Everything3_CreateSearchState(); @@ -187,9 +189,10 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_ClearSearchPropertyRequests(searchState); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_NAME); - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); + //_ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequestHighlighted(searchState, EVERYTHING3_PROPERTY_ID_PATH); _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_PATH_AND_NAME); - _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); + if (includeRunCount) + _ = Everything3ApiDllImport.Everything3_AddSearchPropertyRequest(searchState, EVERYTHING3_PROPERTY_ID_RUN_COUNT); if (token.IsCancellationRequested) yield break; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs index 6a3d7cb67bf..3490b8b8c4b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs @@ -41,6 +41,8 @@ public enum EverythingSortOption : uint FILE_LIST_FILENAME_ASCENDING = 17u, [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_file_list_filename_descending))] FILE_LIST_FILENAME_DESCENDING = 18u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_run_count_ascending))] + RUN_COUNT_ASCENDING = 19u, [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_run_count_descending))] RUN_COUNT_DESCENDING = 20u, [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_recently_changed_ascending))] From 2eb08edbd05811a9be8a153cbcccd924c416b728 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 3 May 2026 21:40:43 +0800 Subject: [PATCH 33/44] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../Search/Everything/EverythingAPI.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 7d3030c058b..753162c6a4d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -85,7 +85,8 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o EverythingApiDllImport.Everything_SetSort(preparedOption.SortOption); EverythingApiDllImport.Everything_SetMatchPath(preparedOption.IsFullPathSearch); - if (preparedOption.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) + if (preparedOption.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING || + preparedOption.SortOption == EverythingSortOption.RUN_COUNT_ASCENDING) { EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); } From fa3d313b9e8eeb9f44c3db513bda27e5cdc3d3c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 3 May 2026 13:42:28 +0000 Subject: [PATCH 34/44] Add RUN_COUNT_ASCENDING mapping to EverythingApiV3.TryConvertSortOption Agent-Logs-Url: https://github.com/Flow-Launcher/Flow.Launcher/sessions/2cc46565-07b9-4c0c-8b67-f47351658735 Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> --- .../Search/Everything/EverythingApiV3.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index ead5ea09c1b..dc2af1d6bc0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -406,6 +406,10 @@ private static bool TryConvertSortOption(EverythingSortOption sortOption, out ui propertyId = EVERYTHING3_PROPERTY_ID_FILE_LIST_NAME; ascending = false; return true; + case EverythingSortOption.RUN_COUNT_ASCENDING: + propertyId = EVERYTHING3_PROPERTY_ID_RUN_COUNT; + ascending = true; + return true; case EverythingSortOption.RUN_COUNT_DESCENDING: propertyId = EVERYTHING3_PROPERTY_ID_RUN_COUNT; ascending = false; From 6134d46ca61afe8c638b646c682a4c895e658194 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 3 May 2026 21:44:21 +0800 Subject: [PATCH 35/44] Fix wrong message --- .../Search/Everything/EverythingAvailabilityService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs index 565846e214c..db16e778118 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -35,7 +35,7 @@ public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToke throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), - Localize.flowlauncher_plugin_everything_15_unavailable(), + Localize.flowlauncher_plugin_everything_is_not_running(), Constants.EverythingErrorImagePath, ClickToInstallEverythingAsync); } From f4d98e676b5e1efd4c4a0002597118c732dbabce Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 15 May 2026 21:31:58 +0800 Subject: [PATCH 36/44] Allow empty Everything instance name to support Everything 1.5b --- .../Search/Everything/EverythingApiFactory.cs | 10 +--------- .../Search/Everything/EverythingApiV3.cs | 5 +---- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- .../ViewModels/SettingsViewModel.cs | 4 +--- .../Views/ExplorerSettings.xaml | 4 ++-- 5 files changed, 6 insertions(+), 19 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs index 609222dd097..24187a64ff9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs @@ -4,19 +4,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { internal static class EverythingApiFactory { - internal const string DefaultEverything15InstanceName = "1.5a"; - public static IEverythingApi Create(Settings settings) { - ArgumentNullException.ThrowIfNull(settings); - return settings.EnableEverything15Support - ? new EverythingApiV3(GetNormalizedInstanceName(settings.Everything15InstanceName)) + ? new EverythingApiV3(settings.Everything15InstanceName) : new LegacyEverythingApi(); } - - internal static string GetNormalizedInstanceName(string instanceName) => string.IsNullOrWhiteSpace(instanceName) - ? DefaultEverything15InstanceName - : instanceName.Trim(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index dc2af1d6bc0..721f7772aad 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -308,13 +308,10 @@ private bool TryUseEverything3Client(Action action) private bool TryConnectEverything3(out IntPtr client) { client = IntPtr.Zero; - var normalizedInstanceName = string.IsNullOrWhiteSpace(_instanceName) - ? EverythingApiFactory.DefaultEverything15InstanceName - : _instanceName.Trim(); try { - client = Everything3ApiDllImport.Everything3_ConnectW(normalizedInstanceName); + client = Everything3ApiDllImport.Everything3_ConnectW(_instanceName); return client != IntPtr.Zero; } catch (DllNotFoundException) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 00ee337ab2e..fe78c810c80 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -166,7 +166,7 @@ public enum ContentIndexSearchEngineOption // This is only used as a flag to determine whether to show the Everything 1.5 support option in the settings UI, and to determine which instance of Everything API to initialize in the EverythingSearchManager. public bool EnableEverything15Support { get; set; } = false; - public string Everything15InstanceName { get; set; } = EverythingApiFactory.DefaultEverything15InstanceName; + public string Everything15InstanceName { get; set; } = string.Empty; #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 31254863868..29738058550 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -692,9 +692,7 @@ public string Everything15InstanceName get => Settings.Everything15InstanceName; set { - var instanceName = string.IsNullOrWhiteSpace(value) - ? EverythingApiFactory.DefaultEverything15InstanceName - : value.Trim(); + var instanceName = value?.Trim() ?? string.Empty; if (Settings.Everything15InstanceName == instanceName) return; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 90a0213c301..1a579dd4d6a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -1,4 +1,4 @@ - Date: Fri, 15 May 2026 21:48:52 +0800 Subject: [PATCH 37/44] Remove api factory --- .../Search/Everything/EverythingApiFactory.cs | 14 -------------- .../Search/Everything/EverythingSearchManager.cs | 5 +++-- 2 files changed, 3 insertions(+), 16 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs deleted file mode 100644 index 24187a64ff9..00000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiFactory.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Flow.Launcher.Plugin.Explorer.Search.Everything -{ - internal static class EverythingApiFactory - { - public static IEverythingApi Create(Settings settings) - { - return settings.EnableEverything15Support - ? new EverythingApiV3(settings.Everything15InstanceName) - : new LegacyEverythingApi(); - } - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 787b5e3bb40..2c7079c975f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -20,7 +20,6 @@ public EverythingSearchManager(Settings settings) { Settings = settings; _availabilityService = new EverythingAvailabilityService(settings); - api = EverythingApiFactory.Create(settings); } public async IAsyncEnumerable SearchAsync(string search, [EnumeratorCancellation] CancellationToken token) @@ -103,7 +102,9 @@ public void InitializeApi(string sdkDirectory) return; EverythingSdkLoader.EnsureLoaded(sdkDirectory, Settings.EnableEverything15Support); - api = EverythingApiFactory.Create(Settings); + api = Settings.EnableEverything15Support + ? new EverythingApiV3(Settings.Everything15InstanceName) + : new LegacyEverythingApi(); isApiInitialized = true; } } From 2aa9765ba0614b29511fc06b35b2e4cccafea34a Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 16 May 2026 01:04:44 +0800 Subject: [PATCH 38/44] Simplify sdk loading --- .../Search/Everything/EverythingSdkLoader.cs | 31 ------------------- .../Everything/EverythingSearchManager.cs | 12 ++++++- 2 files changed, 11 insertions(+), 32 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs deleted file mode 100644 index e36b808c07e..00000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSdkLoader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading; - -namespace Flow.Launcher.Plugin.Explorer.Search.Everything -{ - internal static class EverythingSdkLoader - { - private static readonly SemaphoreSlim _semaphore = new(1, 1); - - public static void EnsureLoaded(string sdkDirectory, bool enableEverything15Support) - { - _semaphore.Wait(); - try - { - if (enableEverything15Support) - { - if (!Everything3ApiDllImport.IsLoaded) - Everything3ApiDllImport.Load(sdkDirectory); - } - else - { - if (!EverythingApiDllImport.IsLoaded) - EverythingApiDllImport.Load(sdkDirectory); - } - } - finally - { - _semaphore.Release(); - } - } - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 2c7079c975f..15ba590dcf5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -101,7 +101,17 @@ public void InitializeApi(string sdkDirectory) if (isApiInitialized) return; - EverythingSdkLoader.EnsureLoaded(sdkDirectory, Settings.EnableEverything15Support); + if (Settings.EnableEverything15Support) + { + if (!Everything3ApiDllImport.IsLoaded) + Everything3ApiDllImport.Load(sdkDirectory); + } + else + { + if (!EverythingApiDllImport.IsLoaded) + EverythingApiDllImport.Load(sdkDirectory); + } + api = Settings.EnableEverything15Support ? new EverythingApiV3(Settings.Everything15InstanceName) : new LegacyEverythingApi(); From 290ade816db66f6dc2139bbd6657215b6e9d5b89 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 16 May 2026 01:13:12 +0800 Subject: [PATCH 39/44] minor fixes --- .../Search/Everything/EverythingApiV3.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 721f7772aad..3da4be35f45 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -228,8 +228,6 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_DestroyClient(client); } - - await Task.CompletedTask; } private static bool TryCreateSearchResult(IntPtr resultList, nuint resultIndex, out SearchResult result) @@ -307,21 +305,8 @@ private bool TryUseEverything3Client(Action action) private bool TryConnectEverything3(out IntPtr client) { - client = IntPtr.Zero; - - try - { - client = Everything3ApiDllImport.Everything3_ConnectW(_instanceName); - return client != IntPtr.Zero; - } - catch (DllNotFoundException) - { - return false; - } - catch (EntryPointNotFoundException) - { - return false; - } + client = Everything3ApiDllImport.Everything3_ConnectW(_instanceName); + return client != IntPtr.Zero; } /// From 8409f3933fc36576bcbbc5b03d674bc73c873d84 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 16 May 2026 01:14:51 +0800 Subject: [PATCH 40/44] Code cleanup --- .../Search/Everything/EverythingApiV3.cs | 16 ---------------- .../Search/Everything/EverythingHelper.cs | 12 ------------ .../Search/Everything/EverythingStateCode.cs | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 28 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingStateCode.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 3da4be35f45..ae763d1efa1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -287,22 +287,6 @@ private static List GetHighlightData(IntPtr resultList, nuint resultIndex) : []; } - private bool TryUseEverything3Client(Action action) - { - if (!TryConnectEverything3(out var client)) - return false; - - try - { - action(client); - return true; - } - finally - { - _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - } - } - private bool TryConnectEverything3(out IntPtr client) { client = Everything3ApiDllImport.Everything3_ConnectW(_instanceName); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs index 0be29b4ab57..b3f92773867 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingHelper.cs @@ -4,18 +4,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public enum EverythingStateCode - { - OK, - MemoryError, - IPCError, - RegisterClassExError, - CreateWindowError, - CreateThreadError, - InvalidIndexError, - InvalidCallError - } - public static class EverythingHelper { #region Query diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingStateCode.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingStateCode.cs new file mode 100644 index 00000000000..1f7d226504a --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingStateCode.cs @@ -0,0 +1,14 @@ +namespace Flow.Launcher.Plugin.Explorer.Search.Everything +{ + public enum EverythingStateCode + { + OK, + MemoryError, + IPCError, + RegisterClassExError, + CreateWindowError, + CreateThreadError, + InvalidIndexError, + InvalidCallError + } +} From bf4565b7bf295b8bbb7ca606ccd4e9c6459cb67a Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 16 May 2026 01:31:15 +0800 Subject: [PATCH 41/44] minor --- .../Search/Everything/EverythingApiV3.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index ae763d1efa1..3b5559ace3d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -147,10 +147,9 @@ public bool IsFastSortOption(EverythingSortOption sortOption) finally { _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - CheckAndThrowExceptionOnErrorFromEverything3(); } - return true; + return false; } private static async IAsyncEnumerable SearchWithEverything3Async(IntPtr client, From 0be6a369ba5c1492c1884b6a1989651d67f65fe6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 16 May 2026 01:42:03 +0800 Subject: [PATCH 42/44] Rework UI hints --- .../Languages/en.xaml | 5 ++-- .../ViewModels/SettingsViewModel.cs | 14 ++++++++--- .../Views/ExplorerSettings.xaml | 24 +++++++++++++------ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index af9d61177ea..2b85e2a0297 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -44,7 +44,7 @@ Date and time format Sort Option: Everything Path: - Everything 1.5 instance name (requires app restart): + Everything 1.5 instance name: Launch Hidden Editor Path Shell Path @@ -191,7 +191,8 @@ Search Full Path Enable File/Folder Run Count - Use Everything 1.5 (requires app restart) + Use Everything 1.5 + Restart Flow Launcher for this change to take effect Click to launch or install Everything Everything Installation diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 29738058550..16023ea7441 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -29,13 +29,15 @@ public partial class SettingsViewModel : BaseModel public IReadOnlyList> PathEnumerationEngines { get; set; } // Cache when initializing - private readonly bool UsingEverything15; + private readonly bool InitialUsingEverything15; + private readonly string InitialEverything15InstanceName; public SettingsViewModel(PluginInitContext context, Settings settings) { Context = context; Settings = settings; - UsingEverything15 = settings.EnableEverything15Support; + InitialUsingEverything15 = settings.EnableEverything15Support; + InitialEverything15InstanceName = settings.Everything15InstanceName; InitializeEngineSelection(); InitializeActionKeywordModels(); } @@ -650,7 +652,7 @@ public string SortOptionWarningMessage } catch (IPCErrorException) { - return UsingEverything15 + return InitialUsingEverything15 ? Localize.flowlauncher_plugin_everything_15_sort_warning() : Localize.flowlauncher_plugin_everything_is_not_running(); } @@ -684,9 +686,14 @@ public bool EnableEverything15Support OnPropertyChanged(); OnPropertyChanged(nameof(FastSortWarningVisibility)); OnPropertyChanged(nameof(SortOptionWarningMessage)); + OnPropertyChanged(nameof(Everything15RestartRequired)); } } + public bool Everything15RestartRequired => + Settings.EnableEverything15Support != InitialUsingEverything15 || + (Settings.EnableEverything15Support && Settings.Everything15InstanceName != InitialEverything15InstanceName); + public string Everything15InstanceName { get => Settings.Everything15InstanceName; @@ -703,6 +710,7 @@ public string Everything15InstanceName { OnPropertyChanged(nameof(FastSortWarningVisibility)); OnPropertyChanged(nameof(SortOptionWarningMessage)); + OnPropertyChanged(nameof(Everything15RestartRequired)); } OnPropertyChanged(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 1a579dd4d6a..37607d8dbe3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -608,6 +608,7 @@ + @@ -640,17 +641,26 @@ Text="{Binding Everything15InstanceName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, TargetNullValue=''}" Visibility="{Binding EnableEverything15Support, Converter={StaticResource BooleanToVisibilityConverter}}" /> - + + Date: Sat, 16 May 2026 22:34:48 +0800 Subject: [PATCH 43/44] Clean up code --- .../Search/Everything/EverythingAPI.cs | 4 +++ .../Search/Everything/EverythingApiV3.cs | 4 +++ .../EverythingAvailabilityService.cs | 30 +++++++------------ .../Everything/EverythingSearchManager.cs | 12 ++++---- .../Search/Everything/IEverythingApi.cs | 3 ++ 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 753162c6a4d..02e785a42e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -15,6 +15,10 @@ public class LegacyEverythingApi : IEverythingApi // cached buffer to remove redundant allocations. private static readonly StringBuilder buffer = new(BufferSize); + public string UnavailableMessage => Localize.flowlauncher_plugin_everything_is_not_running(); + public string UnavailableResolution => Localize.flowlauncher_plugin_everything_click_to_launch_or_install(); + public bool SupportsInstall => true; + const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index 3b5559ace3d..ead28249e29 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -16,6 +16,10 @@ public class EverythingApiV3 : IEverythingApi private readonly string _instanceName; + public string UnavailableMessage => Localize.flowlauncher_plugin_everything_15_unavailable(); + public string UnavailableResolution => Localize.flowlauncher_plugin_everything_15_resolution(); + public bool SupportsInstall => false; + public EverythingApiV3(string instanceName) { _instanceName = instanceName; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs index db16e778118..023bee15db8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs @@ -9,36 +9,26 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything internal class EverythingAvailabilityService { private readonly Settings _settings; + private readonly IEverythingApi _api; - public EverythingAvailabilityService(Settings settings) + public EverythingAvailabilityService(Settings settings, IEverythingApi api) { _settings = settings; + _api = api; } - public async ValueTask EnsureAvailableAsync(IEverythingApi api, CancellationToken token = default) + public async ValueTask EnsureAvailableAsync(CancellationToken token = default) { try { - if (!await api.IsEverythingRunningAsync(token)) - { - if (api is EverythingApiV3) - { - throw new EngineNotAvailableException( - Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Localize.flowlauncher_plugin_everything_15_resolution(), - Localize.flowlauncher_plugin_everything_15_unavailable(), - Constants.EverythingErrorImagePath, - ClickToInstallEverythingAsync); - } - else - { - throw new EngineNotAvailableException( + if (!await _api.IsEverythingRunningAsync(token)) + { + throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), - Localize.flowlauncher_plugin_everything_is_not_running(), + _api.UnavailableResolution, + _api.UnavailableMessage, Constants.EverythingErrorImagePath, - ClickToInstallEverythingAsync); - } + _api.SupportsInstall ? ClickToInstallEverythingAsync : null); } } catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 15ba590dcf5..5a1361762fc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -11,7 +11,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { private Settings Settings { get; } - private readonly EverythingAvailabilityService _availabilityService; + private EverythingAvailabilityService _availabilityService; private readonly Lock _syncRoot = new(); private bool isApiInitialized; private IEverythingApi api; @@ -19,18 +19,17 @@ public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IP public EverythingSearchManager(Settings settings) { Settings = settings; - _availabilityService = new EverythingAvailabilityService(settings); } public async IAsyncEnumerable SearchAsync(string search, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(api, token); + await _availabilityService.EnsureAvailableAsync(token); if (token.IsCancellationRequested) yield break; var option = new EverythingSearchOption(search, - Settings.SortOption, + Settings.SortOption, MaxCount: Settings.MaxResult, IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); @@ -42,7 +41,7 @@ public async IAsyncEnumerable SearchAsync(string search, [Enumerat public async IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(api, token); + await _availabilityService.EnsureAvailableAsync(token); if (!Settings.EnableEverythingContentSearch) { @@ -77,7 +76,7 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc public async IAsyncEnumerable EnumerateAsync(string path, string search, bool recursive, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(api, token); + await _availabilityService.EnsureAvailableAsync(token); if (token.IsCancellationRequested) yield break; @@ -115,6 +114,7 @@ public void InitializeApi(string sdkDirectory) api = Settings.EnableEverything15Support ? new EverythingApiV3(Settings.Everything15InstanceName) : new LegacyEverythingApi(); + _availabilityService = new EverythingAvailabilityService(Settings, api); isApiInitialized = true; } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs index 3c7ed7e896a..bd2e3c0e6e9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs @@ -6,6 +6,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public interface IEverythingApi { + string UnavailableMessage { get; } + string UnavailableResolution { get; } + bool SupportsInstall { get; } ValueTask IsEverythingRunningAsync(CancellationToken token = default); IAsyncEnumerable SearchAsync(EverythingSearchOption option, CancellationToken token = default); Task IncrementRunCounterAsync(string fileOrFolder); From 0e5812e034b4d9dc8d4e27059cc8f9ce0fdbdabf Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 17 May 2026 00:21:56 +0800 Subject: [PATCH 44/44] Cleanup --- .../Search/Everything/EverythingAPI.cs | 39 +++++----- .../Search/Everything/EverythingApiV3.cs | 23 +++--- .../EverythingAvailabilityService.cs | 72 ------------------ .../Everything/EverythingSearchManager.cs | 76 ++++++++++++++++--- .../Search/Everything/IEverythingApi.cs | 5 +- 5 files changed, 101 insertions(+), 114 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 02e785a42e5..3c386f710f3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin.Explorer.Exceptions; using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; namespace Flow.Launcher.Plugin.Explorer.Search.Everything @@ -15,10 +17,6 @@ public class LegacyEverythingApi : IEverythingApi // cached buffer to remove redundant allocations. private static readonly StringBuilder buffer = new(BufferSize); - public string UnavailableMessage => Localize.flowlauncher_plugin_everything_is_not_running(); - public string UnavailableResolution => Localize.flowlauncher_plugin_everything_click_to_launch_or_install(); - public bool SupportsInstall => true; - const uint EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME = 0x00000004u; const uint EVERYTHING_REQUEST_RUN_COUNT = 0x00000400u; @@ -34,7 +32,19 @@ public bool IsFastSortOption(EverythingSortOption sortOption) return fastSortOptionEnabled; } - public async ValueTask IsEverythingRunningAsync(CancellationToken token = default) + /// + /// Searches using the specified criteria and resets the Everything API afterwards. + /// + /// The search criteria. + /// A cancellation token that stops the current search when cancellation is requested. + /// An asynchronous sequence of search results that match the specified criteria. + public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) + { + await foreach (var result in SearchCoreAsync(option, token)) + yield return result; + } + + public async Task CheckAvailableAsync(CancellationToken token = default) { try { @@ -42,13 +52,14 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = } catch (OperationCanceledException) { - return false; + return; } try { _ = EverythingApiDllImport.Everything_GetMajorVersion(); - return EverythingApiDllImport.Everything_GetLastError() != EverythingStateCode.IPCError; + if (EverythingApiDllImport.Everything_GetLastError() == EverythingStateCode.IPCError) + throw new IPCErrorException(); } finally { @@ -56,13 +67,7 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = } } - /// - /// Searches using the specified criteria and resets the Everything API afterwards. - /// - /// The search criteria. - /// A cancellation token that stops the current search when cancellation is requested. - /// An asynchronous sequence of search results that match the specified criteria. - public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) + private async IAsyncEnumerable SearchCoreAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token) { var query = EverythingHelper.PrepareQuery(option); var preparedOption = query.Option; @@ -110,13 +115,11 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o for (var idx = 0; idx < EverythingApiDllImport.Everything_GetNumResults(); ++idx) { if (token.IsCancellationRequested) - { yield break; - } EverythingApiDllImport.Everything_GetResultFullPathNameW(idx, buffer, BufferSize); - var result = new SearchResult + yield return new SearchResult { FullPath = buffer.ToString(), Type = EverythingApiDllImport.Everything_IsFolderResult(idx) ? ResultType.Folder : @@ -125,8 +128,6 @@ public async IAsyncEnumerable SearchAsync(EverythingSearchOption o Score = Convert.ToInt32(EverythingApiDllImport.Everything_GetResultRunCount((uint)idx)), HighlightData = EverythingHelper.EverythingHighlightStringToHighlightList(EverythingApiDllImport.Everything_GetResultHighlightedFileName((uint)idx)) }; - - yield return result; } } finally diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs index ead28249e29..dedfbe91e6f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiV3.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin.Explorer.Exceptions; using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; namespace Flow.Launcher.Plugin.Explorer.Search.Everything @@ -16,10 +17,6 @@ public class EverythingApiV3 : IEverythingApi private readonly string _instanceName; - public string UnavailableMessage => Localize.flowlauncher_plugin_everything_15_unavailable(); - public string UnavailableResolution => Localize.flowlauncher_plugin_everything_15_resolution(); - public bool SupportsInstall => false; - public EverythingApiV3(string instanceName) { _instanceName = instanceName; @@ -46,7 +43,13 @@ public EverythingApiV3(string instanceName) const uint EVERYTHING3_ERROR_INVALID_PARAMETER = 0xE0000004; const uint EVERYTHING3_ERROR_PROPERTY_NOT_FOUND = 0xE0000007; - public async ValueTask IsEverythingRunningAsync(CancellationToken token = default) + public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) + { + await foreach (var result in SearchCoreAsync(option, token)) + yield return result; + } + + public async Task CheckAvailableAsync(CancellationToken token = default) { try { @@ -54,16 +57,14 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = } catch (OperationCanceledException) { - return false; + return; } try { if (!TryConnectEverything3(out var client)) - return false; - + throw new IPCErrorException(); _ = Everything3ApiDllImport.Everything3_DestroyClient(client); - return true; } finally { @@ -71,7 +72,7 @@ public async ValueTask IsEverythingRunningAsync(CancellationToken token = } } - public async IAsyncEnumerable SearchAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token = default) + private async IAsyncEnumerable SearchCoreAsync(EverythingSearchOption option, [EnumeratorCancellation] CancellationToken token) { var query = EverythingHelper.PrepareQuery(option); var preparedOption = query.Option; @@ -231,6 +232,8 @@ private static async IAsyncEnumerable SearchWithEverything3Async(I _ = Everything3ApiDllImport.Everything3_DestroyClient(client); } + + await Task.CompletedTask; } private static bool TryCreateSearchResult(IntPtr resultList, nuint resultIndex, out SearchResult result) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs deleted file mode 100644 index 023bee15db8..00000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAvailabilityService.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using Flow.Launcher.Plugin.Explorer.Exceptions; - -namespace Flow.Launcher.Plugin.Explorer.Search.Everything -{ - internal class EverythingAvailabilityService - { - private readonly Settings _settings; - private readonly IEverythingApi _api; - - public EverythingAvailabilityService(Settings settings, IEverythingApi api) - { - _settings = settings; - _api = api; - } - - public async ValueTask EnsureAvailableAsync(CancellationToken token = default) - { - try - { - if (!await _api.IsEverythingRunningAsync(token)) - { - throw new EngineNotAvailableException( - Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - _api.UnavailableResolution, - _api.UnavailableMessage, - Constants.EverythingErrorImagePath, - _api.SupportsInstall ? ClickToInstallEverythingAsync : null); - } - } - catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) - { - throw new EngineNotAvailableException( - Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Localize.flowlauncher_plugin_everything_architecture_check(), - Constants.GeneralSearchErrorImagePath, - Localize.flowlauncher_plugin_everything_sdk_issue()); - } - } - - private async ValueTask ClickToInstallEverythingAsync(ActionContext _) - { - try - { - var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(_settings.EverythingInstalledPath, Main.Context.API); - - if (installedPath == null) - { - Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_not_found()); - Main.Context.API.LogError(nameof(EverythingAvailabilityService), "Unable to find Everything.exe"); - - return false; - } - - _settings.EverythingInstalledPath = installedPath; - Process.Start(installedPath, "-startup"); - - return true; - } - catch (Exception e) - { - Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_install_issue()); - Main.Context.API.LogException(nameof(EverythingAvailabilityService), "Failed to install Everything", e); - - return false; - } - } - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index 5a1361762fc..98fbe240067 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -11,7 +12,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { private Settings Settings { get; } - private EverythingAvailabilityService _availabilityService; private readonly Lock _syncRoot = new(); private bool isApiInitialized; private IEverythingApi api; @@ -23,15 +23,15 @@ public EverythingSearchManager(Settings settings) public async IAsyncEnumerable SearchAsync(string search, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(token); + await EnsureAvailableAsync(token); if (token.IsCancellationRequested) yield break; - var option = new EverythingSearchOption(search, + var option = new EverythingSearchOption(search, Settings.SortOption, - MaxCount: Settings.MaxResult, - IsFullPathSearch: Settings.EverythingSearchFullPath, + MaxCount: Settings.MaxResult, + IsFullPathSearch: Settings.EverythingSearchFullPath, IsRunCounterEnabled: Settings.EverythingEnableRunCount); await foreach (var result in api.SearchAsync(option, token)) @@ -41,7 +41,7 @@ public async IAsyncEnumerable SearchAsync(string search, [Enumerat public async IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(token); + await EnsureAvailableAsync(token); if (!Settings.EnableEverythingContentSearch) { @@ -52,7 +52,6 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc _ => { Settings.EnableEverythingContentSearch = true; - return ValueTask.FromResult(true); }); } @@ -76,7 +75,7 @@ public async IAsyncEnumerable ContentSearchAsync(string plainSearc public async IAsyncEnumerable EnumerateAsync(string path, string search, bool recursive, [EnumeratorCancellation] CancellationToken token) { - await _availabilityService.EnsureAvailableAsync(token); + await EnsureAvailableAsync(token); if (token.IsCancellationRequested) yield break; @@ -114,11 +113,70 @@ public void InitializeApi(string sdkDirectory) api = Settings.EnableEverything15Support ? new EverythingApiV3(Settings.Everything15InstanceName) : new LegacyEverythingApi(); - _availabilityService = new EverythingAvailabilityService(Settings, api); isApiInitialized = true; } } + private async Task EnsureAvailableAsync(CancellationToken token) + { + var engineName = Enum.GetName(Settings.IndexSearchEngineOption.Everything)!; + try + { + await api.CheckAvailableAsync(token); + } + catch (OperationCanceledException) + { + // ignore, the search was cancelled + } + catch (Exceptions.IPCErrorException) when (api is LegacyEverythingApi) + { + throw new EngineNotAvailableException(engineName, + Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), + Localize.flowlauncher_plugin_everything_is_not_running(), + Constants.EverythingErrorImagePath, + ClickToInstallEverythingAsync); + } + catch (Exceptions.IPCErrorException) + { + throw new EngineNotAvailableException(engineName, + Localize.flowlauncher_plugin_everything_15_resolution(), + Localize.flowlauncher_plugin_everything_15_unavailable(), + Constants.EverythingErrorImagePath); + } + catch (Exception ex) when (ex is DllNotFoundException || ex is EntryPointNotFoundException) + { + throw new EngineNotAvailableException(engineName, + Localize.flowlauncher_plugin_everything_architecture_check(), + Constants.GeneralSearchErrorImagePath, + Localize.flowlauncher_plugin_everything_sdk_issue()); + } + } + + private async ValueTask ClickToInstallEverythingAsync(ActionContext _) + { + try + { + var installedPath = await EverythingDownloadHelper.PromptDownloadIfNotInstallAsync(Settings.EverythingInstalledPath, Main.Context.API); + + if (installedPath == null) + { + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_not_found()); + Main.Context.API.LogError(nameof(EverythingSearchManager), "Unable to find Everything.exe"); + return false; + } + + Settings.EverythingInstalledPath = installedPath; + Process.Start(installedPath, "-startup"); + return true; + } + catch (Exception e) + { + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_install_issue()); + Main.Context.API.LogException(nameof(EverythingSearchManager), "Failed to install Everything", e); + return false; + } + } + public bool IsFastSortOption(EverythingSortOption sortOption) => api.IsFastSortOption(sortOption); public Task IncrementRunCounterAsync(string fileOrFolder) => api.IncrementRunCounterAsync(fileOrFolder); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs index bd2e3c0e6e9..74a453b8e7e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/IEverythingApi.cs @@ -6,10 +6,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public interface IEverythingApi { - string UnavailableMessage { get; } - string UnavailableResolution { get; } - bool SupportsInstall { get; } - ValueTask IsEverythingRunningAsync(CancellationToken token = default); + Task CheckAvailableAsync(CancellationToken token = default); IAsyncEnumerable SearchAsync(EverythingSearchOption option, CancellationToken token = default); Task IncrementRunCounterAsync(string fileOrFolder); bool IsFastSortOption(EverythingSortOption sortOption);