注册和分发属性处理程序

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

本主题的组织方式如下:

注册和分发属性处理程序

实现属性处理程序后,必须注册它,并且其文件扩展名必须与处理程序相关联。 以下示例使用 .recipe 扩展演示了执行此操作所需的注册表项。

HKEY_CLASSES_ROOT
   CLSID
      {50d9450f-2a80-4f08-93b9-2eb526477d1a}
         (Default) = Recipe Property Handler
         ManualSafeSave [REG_DWORD] = 00000001
         InProcServer32
            (Default) = C:\\SDK\\PropertyHandlerSample\\bin\\RecipeHandlers.dll
            ThreadingModel = Apartment
HKEY_LOCAL_MACHINE
   SOFTWARE
      Microsoft
         Windows
            CurrentVersion
               PropertySystem
                  PropertyHandlers
                     .recipe
                        (Default) = {50d9450f-2a80-4f08-93b9-2eb526477d1a}

特定文件类型的属性处理程序通常与创建或操作该类型文件的应用程序 () 一起分发。 但是,你还应考虑使属性处理程序独立于这些应用程序提供,以便在索引器使用属性处理程序但不需要其附带的应用程序的服务器方案中支持文件类型的索引编制。 如果为属性处理程序创建独立安装包,请确保它包括以下内容:

  • 注册和分发属性处理程序主题中指定的 属性处理程序注册详细信息。
  • 注册文件类型和必须安装的任何架构文件,使客户端能够访问属性处理程序的所有功能。

属性处理程序的性能和可靠性注意事项

为特定计算机上的每个文件调用属性处理程序。 在以下情况下通常调用它们:

  • 在为文件编制索引期间。 这是在进程外、具有有限权限的独立进程中完成的。
  • 在 Windows 资源管理器中访问文件以读取和写入属性值时。 这是在进程中完成的。

性能和可靠性指南

用户可能随时拥有数万个任何特定类型的文件 (包括你的) 在其计算机上,并且可以随时访问或修改其中任何或全部文件。 由于经常调用属性处理程序来支持这些访问和修改操作,因此,在繁忙、高度并发的环境中,属性处理程序的性能和可靠性特征至关重要。

在开发和测试属性处理程序时,请记住以下准则。

  • 属性枚举

    属性处理程序在枚举其属性时应具有非常快的响应时间。 应避免对属性值进行内存密集型计算、网络查找或搜索文件本身以外的资源,以确保快速响应时间。

  • 就地写入属性

    如果可能,在处理 (数百 KB 或更大的) 的中型或大型文件时,应排列文件格式,以便读取或写入属性值不需要从磁盘读取整个文件。 即使需要查找文件,也不应将其全部读取到内存中,因为当 Windows 资源管理器或 Windows 搜索索引器尝试访问这些文件或为这些文件编制索引时,该文件会膨胀。 有关详细信息,请参阅 初始化属性处理程序

    实现此目的的一种有用技术是用额外的空间填充文件的标头,以便下次需要写入属性值时,可以就地写入值,而无需重写整个文件。 这需要 ManualSafeSave 功能。 此方法涉及一些额外的风险,即在写入过程中可能会中断文件写入操作, (由于系统故障或) 断电而中断,但由于属性大小通常较小,因此此类中断的概率同样很小,并且通过就地属性写入实现的性能提升被认为足以证明这一额外风险的合理性。 即便如此,你应该注意广泛测试实现,以确保在写入操作过程中发生故障时文件不会损坏。

    最后,使用 ManualSafeSave 实现就地属性写入时,有时无法就地执行操作,并且必须重写整个流。 为了便于重写,处理程序初始化期间提供的流支持 IDestinationStreamFactory 接口。 IDestinationStreamFactory 接口使处理程序实现能够获取用于写入的临时流;完成所有写入并调用 IDestinationStreamFactory::GetDestinationStream 方法时,此流用于完全替换原始文件流。 使用目标流时,原始文件流应被视为只读,因为在调用 IDestinationStreamFactory::GetDestinationStream 方法后,它将被目标流替换。

  • 选择 COM 线程模型

    若要最大程度地提高属性处理程序的效率,应指定它使用 COM 线程模型 Both。 这样就可以从 STA 单元 (Windows 资源管理器直接访问,例如,) 和消息传输代理 (MTA) 单元 (Windows 搜索中的 SearchProtocolHost 进程,例如) ,避免在这些环境中封送处理开销。 若要实现线程模型的全部优势 Both ,还应将处理程序所依赖的任何服务指定为 Both ,以避免在对这些组件的调用中进行任何封送处理。 查看这些特定服务的文档以验证它们是否使用此线程模型。

  • 属性处理程序并发

    属性处理程序和 IPropertyStore 接口专为串行访问而不是并发访问而设计。 Windows 资源管理器、Windows 搜索索引器以及来自 Windows 代码库的所有其他属性处理程序调用保证此用法。 第三方不应有理由同时使用属性处理程序,但无法保证此行为。 此外,即使调用模式预期是串行的, (调用也可能在不同的线程上,例如,当通过 COM RPC 远程调用对象时,如索引器) 中发生的情况。 因此,属性处理程序实现必须支持在不同的线程上调用,理想情况下,并发调用时不应受到任何不良影响。 由于预期的调用模式是串行的,因此在大多数情况下,使用关键部分的普通实现应足以满足这些要求。 通过使用 TryEnterCriticalSection 函数来检测并发调用并失败,避免阻塞并发调用是可以接受的。

  • 文件并发

    属性处理程序通常用于多个应用程序同时访问文件的情况。 因此,处理程序和应用程序需要在打开文件时通过指定适当的共享模式来管理并发性。 他们还需要了解其他应用程序指定的访问权限,并管理不允许访问的情况。 最好是所有使用者都指定自由共享模式,使其他人能够同时访问文件,但在执行此操作时,需要管理一致性问题。 需要在访问文件的应用程序社区上下文中决定要使用的最适当的共享模式。

    文件系统使应用程序能够以一种允许它们控制其他应用程序是否以及如何打开文件的方式打开文件。 共享模式支持读取、写入和删除访问权限。 属性系统支持这些共享模式的子集,如下表所述。

    访问模式 共享模式
    写入 拒绝其他读取者和写入者
    写入 (EnableShareDenyWrite) 启用其他读取者,拒绝其他编写器
    只读 (默认) 启用其他读取者,拒绝其他编写器
    只读 (EnableShareDenyNone) 启用其他读取器和编写器

     

    写入 (GPS_READWRITE) 打开的属性处理程序将拒绝其他读取器和写入器。 处理程序可以通过指定 EnableShareDenyWrite 标志来选择启用读取器的行为, (意味着在注册中启用读取) 。

    属性处理程序打开以供 读取 (GPS_DEFAULT) ,默认情况下启用其他读取器,但拒绝其他编写器。 处理程序可以通过在其注册中指定 EnableShareDenyNone 标志来选择启用其他编写器。 这意味着处理程序可以成功处理在处理程序读取文件时文件内容发生更改的情况。

    有关标志定义,请参阅 GETPROPERTYSTOREFLAGS

了解属性处理程序

使用种类名称

使用属性列表

初始化属性处理程序

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