/// <summary> /// Converts a value to another type. /// </summary> /// <param name="value"> /// The value to convert. /// </param> /// <param name="targetType"> /// The type to convert to. /// </param> /// <param name="parameter"> /// An optional parameter. /// </param> /// <param name="culture"> /// The UI culture to convert to. /// </param> /// <returns> /// The converted value. /// </returns> public object?Convert(object?value, Type targetType, object parameter, CultureInfo culture) { if (targetType != typeof(string)) { throw new InvalidOperationException("Cannot convert to any type except System.String"); } if (value == null) { return(FallbackValue); } var path = (string)value; if (!Path.IsPathRooted(path)) { throw new ArgumentException("Path must be rooted", nameof(value)); } Shell32.IShellItem2 item = Shell32.SHCreateItemFromParsingName <Shell32.IShellItem2>(path); Shell32.SIGDN sigdn = DisplayMode switch { FileNameDisplayMode.Default => Shell32.SIGDN.SIGDN_NORMALDISPLAY, FileNameDisplayMode.FullPath => Shell32.SIGDN.SIGDN_FILESYSPATH, FileNameDisplayMode.NameOnly => Shell32.SIGDN.SIGDN_PARENTRELATIVEPARSING, _ => throw new InvalidOperationException($"Unexpected {nameof(FileNameDisplayMode)}") }; return(item.GetDisplayName(sigdn)); }
// enumerate "God mode" // inspired by the source code of ClassicShell public async Task<SearchResultCollection> SearchAsync(SearchQuery query, CancellationToken ct) { if (string.IsNullOrWhiteSpace(query.QueryString)) return null; var results = new ObservableCollection<SearchResult>(); var resultCollection = new SearchResultCollection { Title = "Control Panel", Icon = new WindowsPEResourceIcon { FilePath = @"C:\windows\system32\control.exe" }, Results = results }; HRESULT hresult; hresult = Shell32.SHGetDesktopFolder(out Shell32.IShellFolder desktopShellFolder); if (hresult != HRESULT.S_OK) throw new Exception($"Shell32.SHGetDesktopFolder returned '{hresult}'"); hresult = Shell32.SHParseDisplayName("shell:::{ED7BA470-8E54-465E-825C-99712043E01C}", IntPtr.Zero, out Shell32.PIDL godmodePidl, 0, out Shell32.SFGAO psfgaoOut); if (hresult != HRESULT.S_OK) throw new Exception($"Shell32.SHParseDisplayName returned '{hresult}'"); var godmodeShellFolder = (Shell32.IShellFolder)desktopShellFolder.BindToObject(godmodePidl, null, new Guid("000214E6-0000-0000-C000-000000000046")); if (godmodeShellFolder == null) throw new Exception($"BindToObject returned null"); var itemEnum = godmodeShellFolder.EnumObjects(IntPtr.Zero, Shell32.SHCONTF.SHCONTF_CHECKING_FOR_CHILDREN | Shell32.SHCONTF.SHCONTF_FLATLIST | Shell32.SHCONTF.SHCONTF_NONFOLDERS | Shell32.SHCONTF.SHCONTF_FOLDERS | Shell32.SHCONTF.SHCONTF_INCLUDEHIDDEN | Shell32.SHCONTF.SHCONTF_INCLUDESUPERHIDDEN | Shell32.SHCONTF.SHCONTF_STORAGE); if (godmodeShellFolder == null) throw new Exception($"EnumObjects returned null"); var itemPidlArr = new IntPtr[1]; while (itemEnum.Next(1, itemPidlArr, out uint fetched) == HRESULT.S_OK && fetched > 0) { var combinedPidl = Shell32.PIDL.Combine(godmodePidl, itemPidlArr[0]); Shell32.SHCreateItemFromIDList(combinedPidl, typeof(Shell32.IShellItem2).GUID, out object shellItemObj); Shell32.IShellItem2 shellItem = (Shell32.IShellItem2)shellItemObj; try { var extractIcon = (Shell32.IExtractIcon)godmodeShellFolder.GetUIObjectOf(IntPtr.Zero, 1, new IntPtr[] { itemPidlArr[0] }, typeof(Shell32.IExtractIcon).GUID, IntPtr.Zero); var iconPathSb = new StringBuilder(255); extractIcon.GetIconLocation(Shell32.GetIconLocationFlags.GIL_FORSHELL, iconPathSb, iconPathSb.Capacity, out int iconIndex, out Shell32.GetIconLocationResultFlags flags); var name = shellItem.GetString(Ole32.PROPERTYKEY.System.ItemNameDisplay).ToString(); var parsingPath = shellItem.GetString(Ole32.PROPERTYKEY.System.ParsingPath).ToString(); var keywords = shellItem.GetString(Ole32.PROPERTYKEY.System.Keywords).ToString().Split(';').Select(x => x.ToLower().Trim()); var queryStringLc = query.QueryString.ToLower(); if (name.ToLower().Contains(queryStringLc) || keywords.Any(x => x.Contains(queryStringLc))) { results.Add(new ActionSearchResult { Title = name, ParentCollection = resultCollection, Icon = new WindowsPEResourceIcon { FilePath = iconPathSb.ToString(), //Index = iconIndex == -1 ? 1 : iconIndex //TODO: support for iconIndex < 0 (which means: find icon by resource id instead of icon index) }, Action = () => { dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")); var folder = shell.NameSpace(@"shell:::{ED7BA470-8E54-465E-825C-99712043E01C}"); foreach (var item in folder.Items) { var itemFolder = ((string)item.path.ToString()); if (itemFolder == parsingPath) item.InvokeVerb("open"); } } }); } } catch (Exception) { } } return resultCollection; }