了解 Windows 搜索中的筛选器处理程序
筛选器处理程序是 IFilter 接口的实现,可扫描文档中的文本和属性。 筛选器处理程序从这些项中提取文本块,筛选出嵌入格式并保留有关文本位置的信息。 他们还提取值区块,这些值是文档属性。 IFilter 是生成更高级别应用程序(如文档索引器和应用程序无关查看器)的基础。
本主题的组织方式如下:
关于 IFilter 接口
Microsoft Windows 搜索使用筛选器提取要包含在全文索引中的项的内容。 可以通过编写筛选器来提取内容和属性处理程序来扩展 Windows 搜索以为新的或专有文件类型编制索引,并编写属性处理程序以提取文件的属性。
IFilter 接口旨在满足全文搜索引擎的特定需求。 全文搜索引擎(如 Windows 搜索)调用 IFilter 方法来提取文本和属性信息并将其添加到索引。 Windows 搜索将返回的 IFilter::GetText 方法的结果拆分为单词,将其规范化,并将其保存在索引中。 如果可用,搜索引擎使用语言代码标识符 (文本区块的 LCID) 来执行特定于语言的断字和规范化。
Windows 搜索使用下表中所述的三个函数访问已注册的筛选器处理程序 (IFilter 接口) 实现。 加载和绑定到嵌入对象的筛选器处理程序时,这些函数特别有用。
函数 | 说明 |
---|---|
LoadIFilter | 获取指向最适合指定内容类型的 IFilter 的指针。 |
BindIFilterFromStorage | 获取指向 IFilter 的指针,该指针最适合 IStorage Interface 对象中包含的内容。 |
BindIFilterFromStream | 获取指向 IFilter 的指针,该指针最适合从流变量检索的指定类标识符 (CLSID) 。 |
IFilter 接口有五种方法,如下表所述。
方法 | 说明 |
---|---|
IFilter::Init | 初始化筛选会话。 |
IFilter::GetChunk | 将 IFilter 置于第一个或下一个区块的开头,并返回描述符。 |
IFilter::GetText | 从当前区块中检索文本。 |
IFilter::GetValue | 从当前区块中检索值。 |
IFilter::BindRegion | 检索表示对象的指定部分的接口。 保留供将来使用。 |
隔离过程
Windows 搜索在具有受限权限的本地系统安全上下文中运行 IFilters。 在此 IFilter 主机隔离过程中,删除了许多权限:
- 受限代码
- 所有人
- Local
- 交互
- 经过身份验证的用户
- 内置用户
- 用户的安全标识符 (SID)
删除这些权限意味着 IFilter 接口无权访问磁盘系统或网络或任何用户界面或剪贴板功能。 此外,隔离进程在作业对象下运行,该对象阻止创建子进程,对工作集施加 100 MB 的限制。 由于未正确实现第三方筛选器的可能性, IFilter 接口主机隔离过程提高了索引平台的稳定性。
注意
必须编写筛选器处理程序以正确管理缓冲区和堆栈。 所有字符串副本都必须具有显式检查,以防止缓冲区溢出。 应始终验证分配的缓冲区大小。 应始终根据缓冲区的大小测试数据的大小。
IFilter DLL
IFilter DLL 实现 IFilter 接口,使客户端能够从文件类型、类或感知类型中提取文本和属性值信息。 Windows 搜索筛选过程 SearchFilterHost.exe 绑定到为项的类、感知类型或名称扩展注册的 IFilter 。
IFilter 结构
每个 IFilter 都是一个 DLL 文件,用于实现进程内组件对象模型, (COM) 服务器提供指定的筛选功能。 下图演示了典型 IFilter DLL 的总体结构。 更复杂的示例可以实现多个 IFilter 类。
本机代码
由于可能的公共语言运行时 (CLR) 运行多个加载项的进程的版本控制问题,必须使用本机代码编写筛选器。 在 Windows 7 及更高版本及更高版本中,显式阻止使用托管代码编写的筛选器。
查找 IFilter 类标识符
IFilter DLL 的类在 PersistentHandler 注册表项下注册。 对于 HTML 文件,以下示例演示了如何查找 HTML 文档的 IFilter DLL。 此示例遵循的逻辑类似于系统用来查找与项关联的 IFilter 的逻辑。
- 检查 DLL 筛选器是否在注册表项 \HKEY_LOCAL_MACHINE\SOFTWARE\Classes 下注册了 PersistentHandler 的文件类型的扩展名。 让此键为
Value1
。 如果该条目已存在,请跳到此过程的步骤 4,并在Value1
该键中使用。 值的类型为 REG_SZ。
\HKEY_LOCAL_MACHINE
SOFTWARE
Classes
.htm
PersistentHandler
{EEC97550-47A9-11CF-B952-00AA0051FE20}
- 或者,如果没有为扩展注册 PersistentHandler,请在注册表项 \HKEY_LOCAL_MACHINE\SOFTWARE\Classes 下查找与文档类型关联的 CLSID。 让此键为
Value2
。
\HKEY_LOCAL_MACHINE
SOFTWARE
Classes
htmlfile
= Class for WWW HTML files
CLSID
{25336920-03F9-11CF-8FD0-00AA00686F13}
- 确定是否为 CLSID 注册了 PersistentHandler。 使用
Value2
步骤 2 中确定的 ,找到 \HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\Value2 条目的 PersistentHandler。 让此键为Value3
。
\HKEY_LOCAL_MACHINE
SOFTWARE
Classes
htmlfile
= Class for WWW HTML files
PersistentHandler
{EEC97550-47A9-11CF-B952-00AA0051FE20}
- 确定 IFilter 永久性处理程序 GUID。 使用
Value1
和Value3
,查找文档类型的 IFilter 持久处理程序 GUID。 注册表项 \HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\Value1 或 3\PersistentAddinsRegistered\ 89BCB740-6119-101A-BCB7-00DD010655AF“/> 下的值生成此文档类型的 IFilter PersistentHandler GUID。 让此键为Value4
。 在此示例中, IFilter 接口 GUID 为 89BCB740-6119-101A-BCB7-00DD010655AF。
HKEY_LOCAL_MACHINE
SOFTWARE
Classes
{EEC97550-47A9-11CF-B952-00AA0051FE20}
= HTML File Persistent Handler
Data type REG_SZ
PersistentAddinsRegistered
{89BCB740-6119-101A-BCB7-00DD010655AF}
Data type REG_SZ
default = {E0CA5340-4534-11CF-B952-00AA0051FE20}
注意
在此示例中,HTML 文档的 IFilter DLL 是nlhtml.dll。
IFilter::GetChunk 和区域设置代码标识符
文本的 LCID 可以在单个文件中更改。 例如,说明手册的文本可能在英语 (en-us) 和西班牙语 (es) 之间交替,或者文本可能包含除主要语言以外的语言的单个单词。 在任一情况下,每次 LCID 更改时 ,IFilter 都必须开始一个新区块。 由于 LCID 用于选择合适的断字符,因此正确标识它非常重要。 如果 IFilter 无法确定文本的区域设置,则它应返回带区块的零 LCID。 返回零的 LCID 会导致 Windows 搜索使用语言自动检测 (LAD) 技术来确定区块的区域设置 ID。 如果 Windows 搜索找不到匹配项,则默认为系统默认区域设置 (,方法是) 调用 GetSystemDefaultLocaleName 函数 。 有关详细信息,请参阅 IFilter::GetChunk、 CHUNK_BREAKTYPE、 CHUNKSTATE 和 STAT_CHUNK。
如果控制文件格式,并且当前不包含区域设置信息,则应添加用户功能以启用正确的区域设置标识。 使用不匹配的断字符可能会导致用户的查询体验不佳。 有关详细信息,请参阅 IWordBreaker。
注意
筛选器与文件类型相关联,由文件扩展名、MIME 类型或 CLSID 表示。 虽然一个筛选器可以处理多个文件类型,但每种类型只能使用一个筛选器。
其他资源
- GitHub 上提供的 IFilterSample 代码示例演示如何创建用于实现 IFilter 接口的 IFilter 基类。
- 有关索引过程的概述,请参阅 索引过程。
- 有关文件类型的概述,请参阅 文件类型。
- 若要查询文件类型的文件关联属性,请参阅 PerceivedTypes、SystemFileAssociations 和应用程序注册。