属性处理程序最佳做法和常见问题解答

本主题说明如何创建和注册属性处理程序以使用 Windows 属性系统。

本主题的组织方式如下:

最佳实践

重写文件系统属性

文件的某些属性由文件系统数据源提供,例如:

  • PKEY_FileName
  • PKEY_Extension
  • PKEY_ModifiedTime

通常,属性处理程序不能为这些属性提供值。 但是,在某些情况下,可以根据属性处理程序提供的注册信息重写这些属性。 属性处理程序使用要重写的属性名称填充 HKEY_CLASSES_ROOT\CLSID\{handler clsid}\OverrideFileSystemProperties 。 这仅限于系统了解的以下列表中所示的一组固定属性。

以下属性值支持重写:

有关所有 Shell 属性的完整列表,请参阅 Shell 属性

重要

重写的属性值仅在为文件编制索引时使用。 因此,从文件系统数据源浏览文件不会显示重写的值。  

以基于 XML 的文件格式存储属性

有两个基本选项可用于以基于 XML 的文件格式存储属性:

  • 根据文档的 XML 架构,使用 XML 元素和属性存储每个属性。 此方法更“对 XML 友好”。
  • 将整个属性存储序列化为内存中的二进制大型对象 (BLOB) ,将 BLOB 转换为 base64 编码的字符串,然后将该字符串存储在 XML 中。 这是这两种方法中更简单的方法,可用于轻松提供对开放元数据的支持。

例如,某些处理程序可能会合并这些方法,以标准 XML 格式存储一些重要值,并将其余值存储在 BLOB 中。

计算属性

某些属性派生自文件的特定属性。 例如, System.Image.Dimensions 属性由图像文件中图像的实际尺寸决定。 由于此类属性值不能由属性处理程序更改,因此它们将在属性说明中标记 isInnate="true" 。 其他属性是从特定属性的一部分或通过聚合多个属性的值来计算的。 由于对这些“计算”属性的更新会在如何更改“源”值方面产生歧义,因此计算属性应在属性说明中标记为 isInnate="true" 只读或报告为只读。 后一个选项可通过指示处理程序从 IPropertyStoreCapabilities::IsPropertyWritable 返回S_FALSE。

常见问题

为什么 Windows 搜索索引器不加载属性处理程序?

Windows 搜索索引器作为系统服务运行,无法加载存储在用户配置文件目录中的 DLL。 如果使用 Microsoft Visual Studio 生成和调试,它会将 DLL 放置在用户配置文件 (中,因此索引器) 不会加载它。 若要解决此问题,请将 DLL 复制到配置文件文件夹 (外部,例如,复制到 C:\Program Files\YourAppName) ,并在其中注册。

有关开发属性处理程序以使用 Windows 搜索索引器的更具体指南,请参阅 为 Windows 搜索开发属性处理程序

应通过“IPropertyStore::GetCount”和“IPropertyStore::GetAt”枚举方法发现哪些属性?

并非所有属性存储对象的客户端都使用这些方法。 某些客户端知道它们计划通过 PKEY 名称) 直接请求 (的属性,或者通过属性说明列表接收属性信息。 属性发现方法支持其他几种方案。 如果属性不需要参与这些方案,则不需要枚举它。 因此,属性处理程序可以为未通过 IPropertyStore::GetCount 和 IPropertyStore::GetAt 方法发现的属性生成非VT_EMPTY值。

但是,如果满足以下任一条件,应通过这些方法查看属性:

  • 如果为属性编制了索引以便可搜索: 这意味着它包含在 Windows 搜索属性存储中, (属性说明架构) 中表示 isColumn = "true" ,或者可用于全文搜索 (inInvertedIndex = "true") 。 如果没有这些标志或缺少属性说明,“string”类型的属性将自动添加到倒排索引以启用搜索。 由于属性系统中已安装属性说明) 的已知属性 (列表非常大, () 超过 800 个属性,因此要求每个属性处理程序在属性系统中注册的每个属性是不切实际的。 相反,索引过程会从属性处理程序中枚举它索引的每个项的相关属性,并使用枚举属性的值来生成全文索引。
  • 如果在复制项的属性集时应复制该属性:若要实现“复制属性集”函数,源项使应通过 IPropertyStore::GetCount 和 IPropertyStore::GetAt 方法复制的属性可见。 不应包含不需要复制或复制没有意义的属性。
  • 如果属性值不为空, (VT_EMPTY) : 空的属性值对客户端没有用。 当客户端尝试返回空属性值时,将返回值 VT_EMPTY。 因此,不应枚举具有空值的属性。
  • 如果在调用“remove properties”函数时应删除该属性: 此功能的存在用于保护隐私;它通过枚举发现属性处理程序中的所有值,并删除用户选择删除的每个值。

注意

如果处理程序支持固定架构 (且不打开元数据) ,则枚举属性不会传达特定属性处理程序支持的属性集。 相反,此类处理程序应记录它们支持的属性集。

 

如何实现知道哪些文件格式支持开放元数据?

有关对开放元数据的支持的信息,请参阅文件类型中的“支持开放元数据的 文件类型”。

是否可以使用属性处理程序存储VT_NULL值?

不是。 调用 IPropertyStore::GetValue 和 IPropertyStore::SetValue 时,VT_NULL值将转换为 VT_EMPTY

“PropVariantChangeType”函数支持哪些日期字符串格式?

通常,表示日期/时间值的属性应使用 VT_FILETIME 表示。 但是,许多数据源以字符串形式提供此信息。 PropVariantChangeType 帮助程序 API 支持将某些字符串日期格式强制转换为 FILETIME 值,如下表所示。

格式 Windows Vista、Windows XP 和 Microsoft Windows 桌面搜索 (WDS) Windows 7 说明
yyyy/mm/dd:hh:mm:ss.uuu Utc;y=year,m=month,d=date,h=hours (24-hour clock) ,m=minutes,s=seconds,u=microseconds
yyyy-mm-ddThh:mm:ssZ ISO8601 格式规范UTC (由“Z”时区指示器表示) ;y=year,m=month,d=date,h=hours (24 小时制) ,m=minutes,s=seconds;“T”是时间部分的分隔符。

是否可以创建只读属性处理程序?

是。 某些属性处理程序实现不支持写入属性值。 这些属性处理程序应在对传递 STGM_READWRITE的 IInitializeXXX::Initialize 的调用或对 IPropertyStore::SetValue 的任何调用时返回STGM_E_ACCESSDENIED。

在STGM_READ模式下打开的所有属性处理程序都应在调用 IPropertyStore::SetValue 时返回STGM_E_ACCESSDENIED。

属性处理程序是否可以将属性视为只读,即使架构指示该属性是可写的?

是。 在架构系统中,属性注释为只读 (包括具有 isInnate = "true") 或读/写的属性。 不支持编写架构认为应可写的特定属性的属性处理程序应实现 IPropertyStoreCapabilities ,并在调用该属性的 IPropertyStoreCapabilities::IsPropertyWritable 时返回S_FALSE。 这表示在此处理程序和此文件的上下文中, 属性不可写。

注意

无法执行反向操作。 不能允许属性处理程序写入在架构中标记为只读的属性