Click here to Skip to main content
16,022,069 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I’m exploring how to customize and extend Windows 11 search to call my API and provide search results from it. I have tried the following approach, but it hasn’t worked:

What I have tried:

**Step 1.** Created a C# class library in .NET 8.

**Step 2.** Defined the SearchResult class:
public class SearchResult
{
    public string Title { get; set; }
    public string Url { get; set; }
    public string Snippet { get; set; }
}

**Step 3.** Created the ISearchProtocol interface:
`using System.Runtime.InteropServices;

namespace MySearchHandler;

[ComVisible(true)]
[Guid("3958f382-369b-4d2f-809c-3bab43e5bf54")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISearchProtocol
{
    void Init();
    void Shutdown();
    string GetNextDocument();
}`

**Step 4.** Implemented the SearchHandler class:
`using Newtonsoft.Json;
using System.Runtime.InteropServices;

namespace MySearchHandler;

[ComVisible(true)]
[Guid("37561b26-cd9f-4afe-9e36-00558430fde7")]
[ClassInterface(ClassInterfaceType.None)]
public class SearchHandler : ISearchProtocol
{
    public void Init()
    {
        // Initialization logic
    }

    public void Shutdown()
    {
        // Cleanup logic
    }

    public async Task<string> GetSearchResultsAsync(string query)
    {
        await Task.CompletedTask;

        return JsonConvert.SerializeObject(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." }
        });
    }

    public string GetNextDocument()
    {
        string query = "example search query"; // Replace with dynamic query
        Task<string> searchResultsTask = GetSearchResultsAsync(query);
        searchResultsTask.Wait(); // Block until the task completes
        return searchResultsTask.Result;
    }
}`

**Step 5.** Updated the class library .csproj settings:
`<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <ComVisible>true</ComVisible>
    <AssemblyName>MySearchHandler</AssemblyName>
    <OutputType>Library</OutputType>
    <GenerateComClass>true</GenerateComClass>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>

</Project>`

**Step 6.** Registered the search handler using the following PowerShell script:
`# Define the CLSID and the path
$clsid = "37561b26-cd9f-4afe-9e36-00558430fde7"
$basePath = "HKLM:\Software\Classes\CLSID\{$clsid}"

# Create the CLSID key
New-Item -Path $basePath -Force

# Set the default value for the CLSID key
Set-ItemProperty -Path $basePath -Name '(Default)' -Value "MySearchHandler.SearchHandler"

# Create the InprocServer32 key
$inprocPath = "$basePath\InprocServer32"
New-Item -Path $inprocPath -Force

# Set the default value and ThreadingModel for InprocServer32
Set-ItemProperty -Path $inprocPath -Name '(Default)' -Value "C:\Users\<userName>\source\repos\MySearchHandler\bin\Release\net8.0\MySearchHandler.dll"
Set-ItemProperty -Path $inprocPath -Name 'ThreadingModel' -Value "Both"

# Create the protocol handler key
$protocolPath = "HKLM:\Software\Microsoft\Windows Search\ProtocolHandlers\MySearchHandler"
New-Item -Path $protocolPath -Force
Set-ItemProperty -Path $protocolPath -Name '(Default)' -Value "MySearchHandler.SearchHandler"`


I am now trying to test it by typing the keyword 'first' in the Windows 11 search box, but I’m not seeing the 'First Result' from the SearchHandler class.

Any help would be greatly appreciated!
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900