开发 Windows Search 的属性处理程序
Microsoft Windows Search 使用属性处理程序从项中提取属性值,并使用属性系统架构来确定应如何为特定属性编制索引。 为了读取属性值并为其编制索引,Windows Search 会在进程外调用属性处理程序,以提高安全性和可靠性。 相比之下,属性处理程序由 Windows 资源管理器在进程内调用,以来读取和写入属性值。
本主题为属性系统主题补充了特定于 Windows Search 的信息,并包含以下部分:
属性处理程序的设计决策
实现属性处理程序涉及以下步骤:
- 制定有关要支持的属性的设计决策。
- 为尚未包含在属性系统中的属性创建属性说明 (.propdesc) 文件。
- 实现并测试属性处理程序。
- 安装并注册属性处理程序和属性说明文件。
- 测试属性处理程序安装和注册。
在开始之前,需要考虑以下设计问题:
- 文件格式支持/应该支持哪些属性?
- 这些属性是否已在系统架构中?
- 是否可以使用系统提供的现有属性处理程序?
- 可以向最终用户显示哪些属性?
- 用户可以编辑哪些属性?
- 对全文搜索的支持应该来自属性处理程序还是筛选器?
- 我需要支持旧版应用程序吗? 如果需要,我要实现什么?
注意
在继续之前,请参阅使用系统提供的属性处理程序,了解是否可以使用系统提供的属性处理程序,从而节省时间和开发资源。
做出这些决定后,可以编写自定义属性的正式说明,以便 Windows Search 引擎可以开始为文件和属性编制索引。 这些正式说明是 XML 文件,如属性说明架构中所述。
属性决策
在考虑支持哪些属性时,应确定用户的索引编制和搜索需求。 例如,你可能能够识别一百个可能对你文件类型有用的属性,但用户可能只对搜索少数几个属性感兴趣。 此外,你可能想要在 Windows 资源管理器中向用户显示不同、更大或更小的属性组,并允许用户仅编辑显示的部分这些属性。
文件类型可以支持你定义的任何自定义属性,以及一组系统定义的属性。 在创建自定义属性之前,请查看系统属性,以查看系统属性是否已定义要支持的属性。 始终确保支持最重要的系统定义属性。
建议使用矩阵来帮助设计属性:
属性名称 | 可编制索引吗? | 可显示吗? | 可编辑吗? |
---|---|---|---|
property1 | Y | Y | N |
property... | Y | Y | N |
propertyn | N | N | N |
对于其中每个属性,需要确定它应具有哪些属性,然后在属性说明 XML 文件 (.propdesc) 中正式描述它们。 属性包括属性的数据类型、标签、帮助字符串等。 对于可索引属性,应特别注意在属性说明文件的 searchInfo XML 元素中找到的以下属性特性。
Attribute | 说明 |
---|---|
inInvertedIndex | 可选。 指示是否应将字符串属性值分解为单词并将每个单词存储在倒排索引中。 倒排索引支持使用 CONTAINS 或 FREETEXT(例如 SELECT ...WHERE CONTAINS "sometext")在属性值上高效搜索单词和短语。 如果设置为 FALSE,则针对整个字符串进行搜索。 大多数字符串属性应将此设置为 TRUE;非字符串属性应将此设置为 FALSE。 默认值为 FALSE。 |
isColumn | 可选。 指示属性是否应作为列存储在 Windows Search 数据库中。 将属性存储为列可以对整个列值进行检索、排序、分组和筛选(即使用除 CONTAINS 或 FREETEXT 之外的任何谓词)。 向用户显示的属性应将此设置为 TRUE,除非它是要在倒排索引中搜索的非常大的文本属性(如文档正文)。 默认值为 FALSE。 |
isColumnSparse | 可选。 指示如果值为 NULL,属性是否不占用空间。 非稀疏属性为每个项占用空间,即使值为 NULL。 如果该属性是多值的,则此属性始终为 TRUE。 仅当每个项目都存在值时,此属性才应为 FALSE。 默认值为 TRUE。 |
columnIndexType | 可选。 为了优化查询,Windows 搜索引擎可以为 isColumn=TRUE 的属性创建辅助索引。 这在索引编制期间需要更多处理和磁盘空间,但在查询期间可提高性能。 如果用户经常对属性进行排序、分组或筛选(即使用 =、!=、<、>、LIKE、MATCHES),则应将此属性设置为“OnDisk”。 默认值为“NotIndexed”。 下面的值是有效的:
|
maxSize | 可选。 指示 Windows Search 数据库中存储的属性值允许的最大大小。 此限制适用于向量的各个元素,而不是向量整体。 超过此大小的值将被截断。 默认值为“128”(字节)。 目前,Windows Search 在计算从文件接受的数据量时不使用 maxSize。 相反,Windows Search 使用的限制是文件大小与从注册表 HKEY_LOCAL_MACHINE->Software->Microsoft->Windows Search->Gathering Manager->MaxGrowFactor 读取的 MaxGrowFactor 的乘积(文件大小 N * MaxGrowFactor)。 默认 MaxGrowFactor 为四 (4)。 因此,如果文件类型的总大小往往较小,但属性较大,则 Windows Search 可能不接受想要发出的所有属性数据。 但是,可以根据需要增大 MaxGrowFactor。 |
注意
对于 columnIndexType 属性,需要权衡加快查询速度的好处与辅助索引可能产生的更多索引时间和空间成本。 不过,只有具有非 null 值的项才需要支付此费用,因此大多数属性都可以将此属性设置为“OnDisk”。
全文支持
一般来说,全文搜索由称为筛选器的组件提供支持;但是,对于文件格式不复杂的基于文本的文件类型,属性处理程序可能能够以较小的开发工作量提供这一功能。 应查看全文内容部分,比较筛选器和属性处理程序功能,以帮助确定最适合文件类型的选项。 特别重要的是,筛选器可以处理每个文件的多个语言代码标识符 (LCID),而属性处理程序则不能。
注意
由于属性处理程序无法像筛选器那样对内容进行分块,因此大文件(即使它们是不复杂的文件格式)必须完全加载到内存中。
操作系统实现注意事项
Windows 7 的实现信息
在 Windows 7 及更高版本中,注册属性处理程序、IFilter 或新扩展时会出现新行为。 安装新的属性处理程序和/或 IFilter 后,会自动对具有相应扩展名的文件重建索引。
在 Windows 7 中,建议将 IFilter 与其相应的属性处理程序一起安装,并在属性处理程序之前注册 IFilter。 注册属性处理程序会立即对以前编制索引的文件重建索引而无需先重启,并且会利用任何先前注册的 IFilter 来进行内容索引编制。
如果仅安装了 IFilter,而没有安装相应的属性处理程序,则在重启索引服务或系统后会发生自动重建索引。
有关特定于 Windows 7 的属性说明标志,请参阅以下参考主题:
Windows Vista 和更早版本的实现信息
在 Windows Vista 之前,筛选器支持分析和枚举文件内容和属性。 通过引入属性系统,属性处理程序处理文件属性,而筛选器处理文件内容。 对于 Windows Vista,只需开发与属性处理程序配合的 IFilter 接口的部分实现,如在 Windows Search 中创建筛选处理程序的最佳做法中所述。
虽然属性系统也包含在 Windows XP 的 Windows Search 安装中,但第三方和旧版应用程序可能需要筛选器处理内容和属性。 因此,如果要在 Windows XP 平台上进行开发,则应为文件类型或自定义属性提供完整的筛选器实现以及属性处理程序。
编写属性说明文件
属性说明 XML 文件 (.propdesc) 的结构在 propertyDescription 主题中进行了描述。 对于搜索来说,searchInfo 元素的属性尤为重要。 决定支持哪些属性后,需要为每个属性创建并注册属性说明文件。 注册 .propdesc 文件时,它们包含在架构的属性说明列表中,并成为搜索引擎属性存储中的列名。
可以使用 PSRegisterPropertySchema 函数(调用架构子系统的 IPropertySystem::RegisterPropertySchema 的包装器 API)注册自定义属性说明。 此函数使用本地计算机上 .propdesc 文件的文件路径(通常是“Program Files”下的应用程序安装目录)通知架构子系统添加属性说明架构 (.propdesc) 文件。 通常,安装程序或应用程序(例如,属性处理程序安装程序)将在安装 .propdesc 文件后调用此方法。
实现属性处理程序
开发属性处理程序涉及实现以下接口:
- IInitialzeWithStream:提供属性处理程序的基于流的初始化。
- IPropertyStore:枚举、获取和设置属性值。
- IPropertyStoreCapabilities:可选。 标识用户是否可以从用户界面编辑属性。
IInitializeWithStream
如属性系统主题中所述,强烈建议使用 IInitializeWithStream 实现属性处理程序以执行基于流的初始化。 如果选择不实现 IInitializeWithStream,则属性处理程序必须通过在属性处理程序的注册表项上设置 DisableProcessIsolation 标志来选择退出在隔离进程中运行。 禁用进程隔离通常仅适用于旧版属性处理程序,应尽力避免任何新代码。
IPropertyStore
要创建属性处理程序,必须使用以下方法实现 IPropertyStore 接口。
方法 | 说明 |
---|---|
提交 | 将属性更改保存到文件。 |
GetAt | 从项的属性数组中检索属性键。 |
GetCount | 获取附加到文件的属性数量。 |
GetValue | 检索特定属性的数据。 |
SetValue | 设置新的属性值或者替换/移除现有值。 |
有关实现此接口的重要注意事项包含在 IPropertyStore 文档中。
注意
如果属性处理程序为给定项的同一属性发出多个值,则只在目录中存储发出的最后一个值。
IPropertyStoreCapabilities
属性处理程序可以选择实现此接口以禁用用户编辑特定属性的能力。 这些属性通常可以在“详细信息”页面和窗格中编辑,但在实现属性处理程序下不允许编辑它们。 与替代方案(来自 Shell 的简单运行时错误)相比,正确实现此接口可提供更好的用户体验。
确保为你的项编制索引
现在已经实现了属性处理程序,接下来需要确保为处理程序注册的项编制索引。 可以使用目录管理器启动重建索引,还可以使用爬网范围管理器设置默认规则来指示要索引器爬网的 URL。 另一种选择是遵循 Windows Search 代码示例中的重新索引代码示例。
安装和注册属性处理程序
实现属性处理程序后,必须注册它并将其文件扩展名与处理程序关联。 以下示例显示了执行此操作所需的注册表项和值。
HKEY_CLASSES_ROOT
CLSID
{<CLSID for property handler>}
(Default) = <Property Handler Name>
InProcServer32
(Default) = <full path to property handler dll>
ThreadingModel = <your threading model>
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
PropertySystem
PropertyHandlers
<.fileextention>
(Default) = {<CLSID for property handler>}
测试属性处理程序并排查其问题
以下列表提供了有关应执行的测试类型的建议:
- 测试从文件类型支持的每个属性获取输出。
- 使用大属性值,例如,在 HTML 文档中使用大型元标记。
- 检查属性处理程序未泄漏文件句柄,方法是在从属性处理程序获取输出后对其进行编辑,或者在枚举文件属性前后使用 oh.exe 等工具。
- 测试与属性处理程序关联的所有文件类型。 例如,检查 HTML 筛选器是否适用于 .htm 和 .html 文件类型。
- 使用损坏的文件进行测试。 正常情况下,属性处理程序应会失败。
- 如果应用程序支持加密,请测试属性处理程序是否未输出加密文本。
- 如果属性处理程序支持全文搜索:
- 在文件内容中使用多个特殊 Unicode 字符并测试其输出。
- 测试对非常大的文档的处理,以确保属性处理程序按预期工作。
安装和设置测试
最后,需要测试安装和卸载例程。
- 安装必须从失败的安装中恢复(例如,在取消然后重启安装后恢复)。
- 卸载必须删除与属性处理程序关联的所有文件。
- 卸载不得删除与属性处理程序安装关联的文件以外的文件。
- 卸载时必须移除与属性处理程序关联的注册表项。
- 即使从安装目录中删除了文件,卸载也必须正常工作。
排查属性处理程序问题
以下是开发属性处理程序时出现的一些常见错误:
- 在用户目录下安装 .propdesc 文件或 DLL。
- 使用相对路径注册组件。
- 在 HKEY_CURRENT_USER 而不是 HKEY_LOCAL_MACHINE 下注册组件。
- 忘记为非流处理程序设置 DisableProcessIsolation。
- 将测试文件置于未编制索引的位置。
如果在让属性处理程序使用索引器时遇到问题,以下是一些可帮助排除故障的提示:
- 验证属性说明文件(.propdesc 文件)是否根据需要标记为 isColumn="true"、isViewable="true" 和 isQueryable="true"。
- 验证 .propdesc 文件是否位于全局位置。
- 验证是否使用绝对路径注册了 .propdesc 文件。
- 验证事件日志没有记录注册 .propdesc 文件的任何失败。
- 验证 DLL 是否位于全局位置(而不是用户配置文件下)。
- 验证 DLL 是否在 HKEY_LOCAL_MACHINE\Software\Classes 下注册。
- 验证 DLL 是否使用完整路径(或使用系统帐户已知的环境变量扩展为绝对路径的 REG_EXPAND_SZ 字符串)注册。
- 验证属性处理程序是否在 Windows 资源管理器下工作。
- 虽然我们建议使用 IInitializeWithStream,但如果必须使用 IInitializeWithFile 或 IInitializeWithItem,请验证是否指定DisableProcessIsolation。
- 验证“索引选项”控制面板是否将文件类型列为索引文件类型。
- 验证测试文件是否位于索引位置。
- 验证自安装属性处理程序以来测试文件是否已修改。
如果测试文件位于索引位置并且索引器已爬网该位置,则需要以某种方式修改该文件才能触发文件的重建索引。
使用系统提供的属性处理程序
Windows 包含许多系统提供的属性处理程序,如果文件类型的格式兼容,就可以使用它们。 如果定义使用其中一种格式的新文件扩展名,则可以通过为文件扩展名注册处理程序类标识符 (CLSID) 来使用系统提供的处理程序。
可以使用下表中列出的 CLSID 来为文件格式类型注册系统提供的属性处理程序。
Format | CLSID |
---|---|
OLE DocFile | {8d80504a-0826-40c5-97e1-ebc68f953792} |
保存游戏 XML | {ECDD6472-2B9B-4b4b-AE36-F316DF3C8D60} |
XPS/OPC 处理程序 | {45670FA8-ED97-4F44-BC93-305082590BFB} |
XML | {c73f6f30-97a0-4ad1-a08f-540d4e9bc7b9} |
在创建自定义属性之前,应确保没有可以改用的系统定义属性。 可以通过调用 PSEnumeratePropertyDescriptions 或使用 prop.exe 命令行工具来枚举系统定义的属性。
系统架构定义了这些属性与索引器的交互方式,无法更改。 此外,用于创建、编辑和保存文件类型的应用程序也需要符合某些行为。 例如,如果应用程序实现安全保存(在编辑过程中创建一个临时文件,然后使用 ReplaceFile() 将新版本替换为旧版本),则它必须将所有属性从原始文件传输到新文件文件。 如果不这样做,则意味着文件会丢失用户或其他应用程序添加的属性。
示例
下面演示了为扩展名为 .OLEDocFile 的文件类型注册系统提供的 OLE DocFile 处理程序。
HKEY_CLASSES_ROOT
SystemFileAssociations
.OLEDocFile
shellex
{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}
(Default) = {9DBD2C50-62AD-11d0-B806-00C04FD706EC}
下面显示了属性列表信息的注册,因此 .OLEDocFile 文件的属性显示在“详细信息”选项卡和窗格中。
HKEY_CLASSES_ROOT
SystemFileAssociations
.OLEDocFile
ExtendedTileInfo = prop:System.ItemType;System.Size;System.DateModified;System.Author;System.OfflineAvailability
FullDetails = prop:System.PropGroup.Description;System.Title;System.Subject;
System.Keywords;System.Category;System.Comment;System.PropGroup.Origin;
System.Author;System.Document.LastAuthor;System.Document.RevisionNumber;
System.Document.Version;System.ApplicationName;System.Company;System.Document.Manager;
System.Document.DateCreated;System.Document.DateSaved;System.Document.DatePrinted;
System.Document.TotalEditingTime;System.PropGroup.Content;System.ContentStatus;
System.ContentType;System.Document.PageCount;System.Document.WordCount;
System.Document.CharacterCount;System.Document.LineCount;
System.Document.ParagraphCount;System.Document.Template;System.Document.Scale;
System.Document.LinksDirty;System.Language;System.PropGroup.FileSystem;
System.ItemNameDisplay;System.ItemType;System.ItemFolderPathDisplay;
System.DateCreated;System.DateModified;System.Size;System.FileAttributes;
System.OfflineAvailability;System.OfflineStatus;System.SharedWith;
System.FileOwner;System.ComputerName
InfoTip = prop:System.ItemType;System.Size;System.DateModified;System.Document.PageCoun
PerceivedType = document
PreviewDetails = prop:*System.DateModified;System.Author;System.Keywords;
*System.Size;System.Title;System.Comment;System.Category;
*System.Document.PageCount;System.ContentStatus;System.ContentType;
*System.OfflineAvailability;*System.OfflineStatus;System.Subject;
*System.DateCreated;*System.SharedWith
相关主题
-
引用
-
Conceptual
-
其他资源