安装和注册协议处理程序 (Windows 搜索)

安装协议处理程序涉及将 DLL 复制到 Program Files 目录中的相应位置,然后通过注册表注册协议处理程序。 安装应用程序还可以添加搜索根和范围规则,以定义 Shell 数据源的默认爬网范围。

本主题按如下所示进行组织:

关于 URL

Windows 搜索使用 URL 唯一标识 Shell 数据源层次结构中的项。 层次结构中第一个节点的 URL 称为 搜索根;Windows 搜索将在搜索根处开始编制索引,请求协议处理程序枚举每个 URL 的子链接。

典型的 URL 结构为:

<protocol>:// [{user SID}/] <localhost>/<path>/[<ItemID>]

下表描述了 URL 语法。

Syntax Description
<协议> 标识要为 URL 调用的协议处理程序。
{user SID} 标识调用协议处理程序时的用户安全上下文。 如果未标识用户安全标识符(SID),则会在系统服务的安全上下文中调用协议处理程序。
<路径> 定义存储的层次结构,其中每个正斜杠('/')是文件夹名称之间的分隔符。
<ItemID> 表示标识子项(例如文件名)的唯一字符串。

 

Windows 搜索索引器会去除 URL 的最后一个斜杠。 因此,不能依赖末尾斜杠的存在来标识目录与条目。 协议处理程序必须能够处理此 URL 语法。 确保选择用于标识 Shell 数据源的协议名称不会与当前数据源冲突。 建议使用此命名约定: companyName.scheme

有关创建 Shell 数据源的详细信息,请参阅 “实现基本文件夹对象接口”。

实现协议处理程序接口

创建协议处理程序需要实现以下三个接口:

  • ISearchProtocol 用于管理 UrlAccessor 对象。
  • IUrlAccessor 用于公开属性,并为 Shell 数据源中的项标识适当的筛选器。
  • IFilter 用于筛选专有文件或枚举和筛选分层存储的文件。

除了列出的三个必需接口之外,其他接口是可选的,并且你可以自由地实现任何可选接口最适合手头的任务。

ISearchProtocol 和 ISearchProtocol2

SearchProtocol 接口初始化和管理您的协议处理器 UrlAccessor 对象。 ISearchProtocol2 接口是 ISearchProtocol 的可选扩展,包含一个额外的方法来指定有关用户和项的详细信息。

Iurlaccessor、iurlaccessor2、iurlaccessor3 和 IUrlAccessor4

下表介绍了 IUrlAccessor 接口。

接口 Description
IUrlAccessor 对于指定的 URL,IUrlAccessor 接口提供对 URL 中公开的项的属性的访问权限。 它还可以将这些属性绑定到特定于协议处理程序的筛选器(即不同于与文件名关联的筛选器)。
IUrlAccessor2 (可选) IUrlAccessor2 接口使用获取项属性及其显示 URL 的代码页的方法扩展 IUrlAccessor,并获取 URL(文档或目录)中的项类型。
IUrlAccessor3 (可选) IUrlAccessor3 接口使用获取用户 SID 数组的方法扩展 IUrlAccessor2,使搜索协议主机能够模拟这些用户为项编制索引。
IUrlAccessor4 (可选) IUrlAccessor4 接口扩展了IUrlAccessor3接口的功能,增加了一个方法,该方法用于识别项的内容是否应编制索引。

 

UrlAccessor 对象由 SearchProtocol 对象实例化和初始化。 IUrlAccessor 接口通过下表中所述的方法提供对重要信息片段的访问。

方法 Description
IUrlAccessor::GetLastModified 返回上次修改 URL 的时间。 如果此时间比索引器上次处理此 URL 的时间更晚,则会调用筛选器处理程序( IFilter 接口的实现)来提取该项的已更改数据。 将忽略目录的修改时间。
IUrlAccessor::IsDirectory 标识 URL 是否表示包含子 URL 的文件夹。
IUrlAccessor::BindToStream 绑定到一个表示自定义数据存储中文件数据的 IStream 接口
IUrlAccessor::BindToFilter 绑定到协议处理程序特定的 IFilter,从而可以公开此项的属性。
IUrlAccessor4::ShouldIndexItemContent 确定项目内容是否需要编制索引。

 

IProtocolHandlerSite

IProtocolHandlerSite 接口用于实例化筛选器处理程序,该处理程序托管在隔离进程中。 为指定的持久性类标识符(CLSID)、文档存储类或文件扩展名获取相应的筛选器处理程序。 要求主机进程绑定到 IFilter 的好处是,主机进程可以管理查找适当的筛选器处理程序的过程,并控制调用处理程序所涉及的安全性。

实现容器的过滤处理程序

如果要实现分层协议处理程序,则必须为枚举子 URL 的容器实现筛选器处理程序。 筛选器处理程序是 IFilter 接口的实现。 枚举过程是对 IFilter 接口的 IFilter::GetChunkIFilter::GetValue 方法的循环迭代。每个子 URL 都作为属性的值公开。

IFilter::GetChunk 返回容器的属性。 若要枚举子URL,IFilter::GetChunk 返回以下任一项:

返回 PKEY_Search_UrlToIndexWithModificationTime 效率更高,因为索引器可以立即确定项是否需要编制索引,而无需调用 ISearchProtocol::CreateAccessorIUrlAccessor::GetLastModified 方法。

以下示例代码演示如何返回 PKEY_Search_UrlToIndexWithModificationTime 属性。

重要

版权(c) Microsoft公司。 保留所有权利。

 

// Parameters are assumed to be valid

HRESULT GetPropVariantForUrlAndTime
    (PCWSTR pszUrl, const FILETIME &ftLastModified, PROPVARIANT **ppPropValue)
{
    *ppPropValue = NULL;

    // Allocate the propvariant pointer.
    size_t const cbAlloc = sizeof(**ppPropValue);
    *ppPropValue = (PROPVARIANT *)CoTaskMemAlloc(cbAlloc));

    HRESULT hr = *ppPropValue ? S_OK : E_OUTOFMEMORY;

    if (SUCCEEDED(hr))
    {
        PropVariantInit(*ppPropValue);  // Zero init the value

        // Now allocate enough memory for 2 nested PropVariants.
        // PKEY_Search_UrlToIndexWithModificationTime is an array of two PROPVARIANTs.
        PROPVARIANT *pVector = (PROPVARIANT *)CoTaskMemAlloc(sizeof(*pVector) * 2);
        hr = pVector ? S_OK : E_OUTOFMEMORY;

        if (SUCCEEDED(hr))
        {
            // Set the container PROPVARIANT to be a vector of two PROPVARIANTS.
            (*ppPropValue)->vt = VT_VARIANT | VT_VECTOR;
            (*ppPropValue)->capropvar.cElems = 2;
            (*ppPropValue)->capropvar.pElems = pVector;
            PWSTR pszUrlAlloc;
            hr = SHStrDup(pszUrl, &pszUrlAlloc);

            if (SUCCEEDED(hr))
            {
                // Now fill the array of PROPVARIANTS.
                // Put the pointer to the URL into the vector.
                (*ppPropValue)->capropvar.pElems[0].vt = VT_LPWSTR; 
                (*ppPropValue)->capropvar.pElems[0].pwszVal = pszUrlAlloc;

                 // Put the FILETIME into vector.
                (*ppPropValue)->capropvar.pElems[1].vt = VT_FILETIME; 
                (*ppPropValue)->capropvar.pElems[1].filetime = ftLastModified;
            }

            else
            {
                CoTaskMemFree(pVector);
            }
        }
 
        if (FAILED(hr))
        {
            CoTaskMemFree(*ppPropValue);
            *ppPropValue = NULL;
        }
    }
    return S_OK;
}

注释

容器 IFilter 组件应始终枚举所有子 URL,即使子 URL 尚未更改,因为索引器会通过枚举过程检测删除。 如果 PKEY_Search_UrlToIndexWithModificationTime 中的日期输出指示数据未更改,则索引器不会更新该 URL 的数据。

 

安装和注册协议处理程序

安装协议处理程序涉及将 DLL 复制到 Program Files 目录中的相应位置,然后注册 DLL(s)。 协议处理程序应实现自注册进行安装。 安装应用程序还可以添加搜索根和范围规则,以定义 Shell 数据源的默认爬网范围,本主题末尾将讨论 如何确保为项目编制索引

注册协议处理程序指南

注册协议处理程序时,应遵循以下准则:

  • 安装程序必须使用 EXE 或 MSI 安装程序。
  • 必须提供发行说明。
  • 必须为每个已安装的加载项创建“添加/删除程序”条目。
  • 安装程序必须接管当前加载项理解的特定文件类型或存储的所有注册表设置。
  • 如果有以前的加载项正在被覆盖,安装程序应通知用户。
  • 如果较新的外接程序覆盖了以前的外接程序,则应能够还原以前的外接程序的功能,并再次使其成为该文件类型的默认外接程序。
  • 安装程序应通过使用爬网范围管理器(CSM)添加搜索根和范围规则来定义索引器的默认爬网范围。

注册协议处理程序

需要在注册表中创建 14 个条目来注册协议处理程序组件,其中:

  • Ver_Ind_ProgID 是协议处理程序实现中版本无关的 ProgID。
  • Ver_Dep_ProgID 是协议处理器实现中的版本依赖 ProgID。
  • CLSID_1 是协议处理程序实现的 CLSID。

注册协议处理程序:

  1. 使用以下键和值注册与版本无关的 ProgID:

    HKEY_CLASSES_ROOT
       <Ver_Ind_ProgID>
          (Default) = <Protocol Handler Class Description>
    
    HKEY_CLASSES_ROOT
       <Ver_Ind_ProgID>
          CLSID
             (Default) = {CLSID_1}
    
    HKEY_CLASSES_ROOT
       <Ver_Ind_ProgID>
          CurVer
             (Default) = <Ver_Dep_ProgID>
    
  2. 使用以下键和值注册与版本相关的 ProgID:

    HKEY_CLASSES_ROOT
       <Ver_Dep_ProgID>
          (Default) = <Protocol Handler Class Description>
    
    HKEY_CLASSES_ROOT
       <Ver_Dep_ProgID>
          CLSID
             (Default) = {CLSID_1}
    
  3. 使用以下键和值注册协议处理程序的 CLSID:

    HKEY_CLASSES_ROOT
       {CLSID_1}
          (Default) = <Protocol Handler Class Description>
    
    HKEY_CLASSES_ROOT
       {CLSID_1}
          {InprocServer32}
             (Default) = <DLL Install Path>
             Threading Model = Both
    
    HKEY_CLASSES_ROOT
       {CLSID_1}
          <ProgID>
             (Default) = <Ver_Dep_ProgID>
    
    HKEY_CLASSES_ROOT
       {CLSID_1}
          <ShellFolder>
             Attributes = dword:a0180000
    
    HKEY_CLASSES_ROOT
       {CLSID_1}
          TypeLib
             (Default) = {LIBID of PH Component}
    
    HKEY_CLASSES_ROOT
       {CLSID_1}
          VersionIndependentProgID
             (Default) = <Ver_Ind_ProgID>
    
  4. 将协议处理程序注册到 Windows 搜索。 在以下示例中, <协议名称> 是协议本身的名称,例如文件、mapi 等:

    HKEY_LOCAL_MACHINE
       SOFTWARE
          Microsoft
             Windows Search
                ProtocolHandlers
                   <Protocol Name> = <Ver_Dep_ProgID>
    
    HKEY_CURRENT_USER
       SOFTWARE
          Microsoft
             Windows Search
                ProtocolHandlers
                   <Protocol Name> = <Ver_Dep_ProgID>
    

    在 Windows Vista 之前:

    HKEY_CURRENT_USER
       SOFTWARE
          Microsoft
             Windows Desktop Search
                DS
                   Index
                      ProtocolHandlers
                         <Protocol Name>
                            HasRequirements = dword:00000000
                            HasStartPage = dword:00000000
    

注册协议处理器的文件类型处理函数

需要在注册表中创建两个条目来注册协议处理程序的文件类型处理程序(也称为 Shell 扩展)。

  1. HKEY_LOCAL_MACHINE
       SOFTWARE
          Microsoft
             Windows
                CurrentVersion
                   Explorer
                      Desktop
                         NameSpace
                            {CLSID of PH Implementation}
                               (Default) = <Shell Implementation Description>
    
  2. HKEY_LOCAL_MACHINE
       SOFTWARE
          Microsoft
             Windows
                CurrentVersion
                   Explorer
                      Shell Extensions
                         Approved
                            {CLSID of PH Implementation} = <Shell Implementation Description>
    

确保对项目进行索引

实现协议处理程序后,您必须指定协议处理程序要索引的 Shell 项。 可以使用目录管理器启动重新编制索引(有关详细信息,请参阅 使用目录管理器)。 或者,还可以使用爬网范围管理器(CSM)设置默认规则,指示索引器要爬网的 URL(有关详细信息,请参阅“使用爬网范围管理器和管理范围规则”)。 还可以添加搜索根(有关详细信息,请参阅 管理搜索根)。 可供您选择的另一个选项是按照 Windows 搜索代码示例中的 ReIndex 示例中的过程执行。

ISearchCrawlScopeManager 接口提供了一些方法,用于通知搜索引擎应对哪些容器进行爬网和/或监视,以及在爬网或监视时要包括或排除的这些容器下的项目。 在 Windows 7 及更高版本中,ISearchCrawlScopeManager2 使用 ISearchCrawlScopeManager2::GetVersion 方法扩展 ISearchCrawlScopeManager,该方法可通知客户端 CSM 的状态是否已更改。

概念

了解协议处理程序

开发协议处理程序

通知索引更改

添加图标和上下文菜单

代码示例:协议处理程序的 Shell 扩展

为协议处理程序创建搜索连接器

调试协议处理程序