using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Flow.Launcher.Plugin.Explorer.Exceptions; using Flow.Launcher.Plugin.Explorer.Search.IProvider; namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { public class WindowsIndexSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider { private Settings Settings { get; } private QueryConstructor QueryConstructor { get; } public WindowsIndexSearchManager(Settings settings) { Settings = settings; QueryConstructor = new QueryConstructor(Settings); } private IAsyncEnumerable WindowsIndexFileContentSearchAsync( ReadOnlySpan querySearchString, CancellationToken token) { if (querySearchString.IsEmpty) return AsyncEnumerable.Empty(); try { return WindowsIndex.WindowsIndexSearchAsync( QueryConstructor.CreateQueryHelper().ConnectionString, QueryConstructor.FileContent(querySearchString), token); } catch (COMException) { // Occurs when the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin // Thrown by QueryConstructor.CreateQueryHelper() return HandledEngineNotAvailableExceptionAsync(); } } private IAsyncEnumerable WindowsIndexFilesAndFoldersSearchAsync( ReadOnlySpan querySearchString, CancellationToken token = default) { try { return WindowsIndex.WindowsIndexSearchAsync( QueryConstructor.CreateQueryHelper().ConnectionString, QueryConstructor.FilesAndFolders(querySearchString), token); } catch (COMException) { // Occurs when the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin // Thrown by QueryConstructor.CreateQueryHelper() return HandledEngineNotAvailableExceptionAsync(); } } private IAsyncEnumerable WindowsIndexTopLevelFolderSearchAsync( ReadOnlySpan search, ReadOnlySpan path, bool recursive, CancellationToken token) { try { return WindowsIndex.WindowsIndexSearchAsync( QueryConstructor.CreateQueryHelper().ConnectionString, QueryConstructor.Directory(path, search, recursive), token); } catch (COMException) { // Occurs when the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin // Thrown by QueryConstructor.CreateQueryHelper() return HandledEngineNotAvailableExceptionAsync(); } } public IAsyncEnumerable SearchAsync(string search, CancellationToken token) { return WindowsIndexFilesAndFoldersSearchAsync(search, token: token); } public IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token) { return WindowsIndexFileContentSearchAsync(contentSearch, token); } public IAsyncEnumerable EnumerateAsync(string path, string search, bool recursive, CancellationToken token) { return WindowsIndexTopLevelFolderSearchAsync(search, path, recursive, token); } private IAsyncEnumerable HandledEngineNotAvailableExceptionAsync() { if (!Settings.WarnWindowsSearchServiceOff) return AsyncEnumerable.Empty(); throw new EngineNotAvailableException( "Windows Index", Localize.plugin_explorer_windowsSearchServiceFix(), Localize.plugin_explorer_windowsSearchServiceNotRunning(), Constants.WindowsIndexErrorImagePath, c => { Settings.WarnWindowsSearchServiceOff = false; // Clears the warning message so user is not mistaken that it has not worked Main.Context.API.ChangeQuery(string.Empty); return ValueTask.FromResult(false); }); } } }