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

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

本主题的组织方式如下:

关于 URL

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

典型的 URL 结构为:

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

下表描述了 URL 语法。

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

 

Windows Search 索引器将剪裁 URL 中的最后一个斜线。 因此,不能依靠是否存在最后一个斜线来标识目录与项。 协议处理程序必须能够处理此 URL 语法。 确保你选择用于标识 Shell 数据源的协议名称不会与当前协议名称冲突。 建议使用此命名约定:companyName.scheme

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

实现协议处理程序接口

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

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

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

ISearchProtocol 和 ISearchProtocol2

SearchProtocol 接口用于初始化和管理协议处理程序 UrlAccessor 对象。 ISearchProtocol2 接口是 ISearchProtocol 的可选扩展,并提供一种额外的方法来指定有关用户和项的详细信息

IUrlAccessor、IUrlAccessor2、IUrlAccessor3 和 IUrlAccessor4

下表介绍了 IUrlAccessor 接口

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

 

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

方法 说明
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 Corporation。 保留所有权利。

 

// 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;
}

注意

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

 

安装和注册协议处理程序

安装协议处理程序涉及将 DLL 复制到 Program Files 目录中的相应位置,然后注册 DLL。 协议处理程序应实现自动注册进行安装。 安装应用程序还可以添加搜索根和范围规则,以定义 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 Search 注册协议处理程序。 在以下示例中,<Protocol Name> 是协议本身的名称,例如文件、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 Search 代码示例中的“重新索引”示例中的过程进行操作。

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

Conceptual

了解协议处理程序

开发协议处理程序

通知索引更改

添加图标和快捷菜单

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

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

调试协议处理程序