using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Vanara.InteropServices; using Vanara.PInvoke; using static Vanara.PInvoke.Ole32; using static Vanara.PInvoke.SearchApi; using static Vanara.PInvoke.Shell32; namespace Vanara.Windows.Shell { /// Represents functionality of the Windows Search Service. public static class ShellSearch { private const string systemCatalog = "SystemIndex"; private static readonly ISearchCatalogManager catMgr; private static readonly ISearchManager mgr = new(); private static readonly IQueryParserManager queryMgr = new(); static ShellSearch() => catMgr = mgr.GetCatalog(systemCatalog); /// Gets search results for a supplied condition against a list of folders. /// The search condition. /// The display name for the search folder. /// The folders in which to perform the search. /// Optional settings for the output view. /// A which contains the search results. public static ShellItem GetSearchResults(SearchCondition condition, string displayName, IEnumerable searchFolders, ShellSearchViewSettings settings = null) { using var cfactory = ComReleaserFactory.Create(new ISearchFolderItemFactory()); cfactory.Item.SetPaths(searchFolders); return GetSearchResults(cfactory.Item, condition, displayName, settings); } /// Gets search results for a supplied condition against a list of folders. /// The search condition. /// The display name for the search folder. /// The folder paths in which to perform the search. /// Optional settings for the output view. /// A which contains the search results. public static ShellItem GetSearchResults(SearchCondition condition, string displayName, IEnumerable searchFolders, ShellSearchViewSettings settings = null) { using var cfactory = ComReleaserFactory.Create(new ISearchFolderItemFactory()); cfactory.Item.SetPaths(searchFolders); return GetSearchResults(cfactory.Item, condition, displayName, settings); } private static ShellItem GetSearchResults(ISearchFolderItemFactory factory, SearchCondition condition, string displayName, ShellSearchViewSettings settings) { factory.SetDisplayName(displayName ?? ""); factory.SetCondition(condition?.condition ?? throw new ArgumentNullException(nameof(condition))); if (settings != null) { factory.SetFolderTypeID(settings.FolderTypeID.Guid()); if (settings.FolderLogicalViewMode.HasValue) factory.SetFolderLogicalViewMode(settings.FolderLogicalViewMode.Value); if (settings.IconSize.HasValue) factory.SetIconSize(settings.IconSize.Value); if (settings.VisibleColumns != null) factory.SetVisibleColumns((uint)settings.VisibleColumns.Length, settings.VisibleColumns); if (settings.SortColumns != null) factory.SetSortColumns((uint)settings.SortColumns.Length, settings.SortColumns); if (settings.GroupColumn.HasValue) factory.SetGroupColumn(settings.GroupColumn.Value); if (settings.StackKeys != null) factory.SetStacks((uint)settings.StackKeys.Length, settings.StackKeys); } return factory.GetShellItem(); } private static ShellItem GetShellItem(this ISearchFolderItemFactory f) => ShellItem.Open(f.GetShellItem()); private static void SetPaths(this ISearchFolderItemFactory f, IEnumerable paths) => SetPaths(f, paths.Select(p => new ShellFolder(p))); private static void SetPaths(this ISearchFolderItemFactory f, IEnumerable paths) { var pa = paths?.ToArray(); if (pa != null && pa.Length > 0) { SHCreateShellItemArrayFromIDLists((uint)pa.Length, Array.ConvertAll(pa, i => (IntPtr)i.PIDL), out var ia).ThrowIfFailed(); f.SetScope(ia); } else f.SetScope(null); } } /// Settings that change the folder view of a search. public class ShellSearchViewSettings { /// The folder logical view mode. The default settings are based on the which is set by the FolderTypeID property. public FOLDERLOGICALVIEWMODE? FolderLogicalViewMode { get; set; } /// The search folder type ID. public FOLDERTYPEID FolderTypeID { get; set; } = FOLDERTYPEID.FOLDERTYPEID_GenericLibrary; /// The group column. If no group column is specified, no grouping occurs. public PROPERTYKEY? GroupColumn { get; set; } /// The search folder icon size. The default settings are based on the which is set by the FolderTypeID property. public int? IconSize { get; set; } /// A list of sort column directions. public SORTCOLUMN[] SortColumns { get; set; } /// A list of stack keys, as specified. If , the folder will not be stacked. public PROPERTYKEY[] StackKeys { get; set; } /// A list of which columns are all visible. The default is based on FolderTypeID. public PROPERTYKEY[] VisibleColumns { get; set; } } }