安装协议处理程序涉及将 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::GetChunk 和 IFilter::GetValue 方法的循环迭代。每个子 URL 都作为属性的值公开。
IFilter::GetChunk 返回容器的属性。 若要枚举子URL,IFilter::GetChunk 返回以下任一项:
-
不包含上次修改时间的项目的 URL。 IFilter::GetValue 返回包含子 URL 的 PROPVARIANT。
PKEY_Search_UrlToIndexWithModificationTime:
URL 和上次修改时间。 IFilter::GetValue 返回一个 PROPVARIANT,其中包含子 URL 的向量和上次修改时间。
返回 PKEY_Search_UrlToIndexWithModificationTime 效率更高,因为索引器可以立即确定项是否需要编制索引,而无需调用 ISearchProtocol::CreateAccessor 和 IUrlAccessor::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。
注册协议处理程序:
使用以下键和值注册与版本无关的 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>使用以下键和值注册与版本相关的 ProgID:
HKEY_CLASSES_ROOT <Ver_Dep_ProgID> (Default) = <Protocol Handler Class Description>HKEY_CLASSES_ROOT <Ver_Dep_ProgID> CLSID (Default) = {CLSID_1}使用以下键和值注册协议处理程序的 CLSID:
HKEY_CLASSES_ROOT {CLSID_1} (Default) = <Protocol Handler Class Description>HKEY_CLASSES_ROOT {CLSID_1} {InprocServer32} (Default) = <DLL Install Path> Threading Model = BothHKEY_CLASSES_ROOT {CLSID_1} <ProgID> (Default) = <Ver_Dep_ProgID>HKEY_CLASSES_ROOT {CLSID_1} <ShellFolder> Attributes = dword:a0180000HKEY_CLASSES_ROOT {CLSID_1} TypeLib (Default) = {LIBID of PH Component}HKEY_CLASSES_ROOT {CLSID_1} VersionIndependentProgID (Default) = <Ver_Ind_ProgID>将协议处理程序注册到 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 扩展)。
-
HKEY_LOCAL_MACHINE SOFTWARE Microsoft Windows CurrentVersion Explorer Desktop NameSpace {CLSID of PH Implementation} (Default) = <Shell Implementation Description> -
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 的状态是否已更改。
相关主题