如何扩展Windows 11搜索能力以调用自定义API并返回搜索结果
自定义Windows 11搜索协议处理器不生效的解决方案
核心问题诊断
你的实现存在以下关键问题,导致搜索结果无法正常显示:
- ISearchProtocol接口定义不符合官方规范:Windows Search要求的协议处理器接口包含特定方法签名,你当前的定义缺少必要方法与参数,无法被系统正确调用。
- 未获取实际搜索查询:代码硬编码了查询字符串,无法响应用户输入的关键词。
- 异步处理逻辑错误:同步方法中使用
Task.Wait()可能引发死锁,导致处理器无法正常返回结果。 - COM注册不完整:.NET 8类库的COM注册需使用官方工具,手动修改注册表可能遗漏关键配置项。
- 搜索结果格式不兼容:返回的自定义JSON结构不符合Windows Search解析要求,系统无法识别展示。
修复步骤
1. 修正ISearchProtocol接口定义
按照Windows Search官方规范重新定义接口及回调:
using System.Runtime.InteropServices; namespace MySearchHandler; [ComVisible(true)] [Guid("3958f382-369b-4d2f-809c-3bab43e5bf54")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISearchProtocol { void Initialize([MarshalAs(UnmanagedType.LPWStr)] string pszProtocol); void SetSite([MarshalAs(UnmanagedType.IUnknown)] object pUnkSite); void GetSite(ref Guid riid, out IntPtr ppvSite); void StartQuery([MarshalAs(UnmanagedType.LPWStr)] string pszQuery, [MarshalAs(UnmanagedType.Interface)] ISearchProtocolCB pProtocolCB); void CancelQuery(); void Shutdown(); } [ComVisible(true)] [Guid("12345678-ABCD-EFGH-IJKL-1234567890AB")] // 替换为专属GUID [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISearchProtocolCB { void ReportResult([MarshalAs(UnmanagedType.LPWStr)] string pszURL, [MarshalAs(UnmanagedType.LPWStr)] string pszTitle, [MarshalAs(UnmanagedType.LPWStr)] string pszDescription, ref PROPVARIANT[] pProps, int dwFlags); } [StructLayout(LayoutKind.Sequential)] public struct PROPVARIANT { public ushort vt; public ushort wReserved1; public ushort wReserved2; public ushort wReserved3; public IntPtr pVal; }
2. 重写SearchHandler实现
修改处理器类,正确获取用户查询并返回系统兼容的结果:
using System.Runtime.InteropServices; namespace MySearchHandler; [ComVisible(true)] [Guid("37561b26-cd9f-4afe-9e36-00558430fde7")] [ClassInterface(ClassInterfaceType.None)] public class SearchHandler : ISearchProtocol { private ISearchProtocolCB _callback; private string _currentQuery; public void Initialize(string pszProtocol) { // 协议初始化逻辑 } public void SetSite(object pUnkSite) { // 设置站点上下文 } public void GetSite(ref Guid riid, out IntPtr ppvSite) { ppvSite = IntPtr.Zero; } public void StartQuery(string pszQuery, ISearchProtocolCB pProtocolCB) { _currentQuery = pszQuery; _callback = pProtocolCB; // 异步处理查询,避免阻塞系统线程 _ = ProcessQueryAsync(); } private async Task ProcessQueryAsync() { try { // 调用API获取结果(替换为你的实际API逻辑) var results = await FetchResultsFromApi(_currentQuery); foreach (var result in results) { var emptyProps = new PROPVARIANT[0]; // 向系统报告单条结果 _callback.ReportResult( result.Url, result.Title, result.Snippet, ref emptyProps, 0 ); } } catch (Exception) { // 异常处理逻辑 } finally { // 报告查询完成(SP_REPORT_DONE标识) _callback.ReportResult(null, null, null, null, 1); } } private async Task<List<SearchResult>> FetchResultsFromApi(string query) { // 模拟API调用延迟 await Task.Delay(100); // 根据用户关键词过滤结果 return new List<SearchResult> { new SearchResult { Title = "First Result", Url = "http://example.com/first", Snippet = "This is the first result." }, new SearchResult { Title = "Second Result", Url = "http://example.com/second", Snippet = "This is the second result." } }.Where(r => r.Title.Contains(query, StringComparison.OrdinalIgnoreCase)).ToList(); } public void CancelQuery() { // 查询取消逻辑 } public void Shutdown() { // 资源清理逻辑 } } public class SearchResult { public string Title { get; set; } public string Url { get; set; } public string Snippet { get; set; } }
3. 更新.csproj配置
启用COM互操作并生成类型库:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0-windows</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <ComVisible>true</ComVisible> <AssemblyName>MySearchHandler</AssemblyName> <OutputType>Library</OutputType> <RegisterForComInterop>true</RegisterForComInterop> <GenerateTypeLib>true</GenerateTypeLib> </PropertyGroup> </Project>
4. 正确注册COM组件
以管理员身份运行PowerShell,执行以下命令:
# 替换为你的DLL实际路径 $dllPath = "C:\Users\<userName>\source\repos\MySearchHandler\bin\Release\net8.0-windows\MySearchHandler.dll" regasm.exe $dllPath /codebase /tlb
5. 创建搜索连接器(.osdx文件)
新建MySearchConnector.osdx文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>My Custom Search</ShortName> <Description>Search results from my API</Description> <InputEncoding>UTF-8</InputEncoding> <Url type="application/x-suggestions+json" template="mysearchhandler://{searchTerms}"/> <Url type="text/html" template="mysearchhandler://{searchTerms}"/> </OpenSearchDescription>
双击该文件,将自定义搜索添加到Windows搜索列表。
6. 重启Windows Search服务
Restart-Service WSearch
验证步骤
- 在Windows搜索框输入
first,检查是否显示自定义结果。 - 若仍无结果,打开事件查看器,查看
Applications and Services Logs > Microsoft > Windows > Search下的错误日志定位问题。
内容的提问来源于stack exchange,提问作者Ved Singhal
相关产品推荐
相关产品推荐

