注册和分发属性处理程序

本主题介绍如何创建和注册属性处理程序以使用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}

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

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

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

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

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

性能和可靠性指南

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

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

  • 属性枚举

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

  • 就地属性写入

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

    实现此目的的一种有用方法是用额外的空间填充文件的标头,以便下次需要写入属性值时,无需重写整个文件即可就地写入该值。 这需要 ManualSafeSave 功能。 此方法涉及一些额外的风险,即由于系统崩溃或电源损失 () ,文件写入操作可能会中断,但由于属性大小通常较小,因此可以通过就地属性写入实现的性能提升被认为足够重要,足以证明这一额外风险。 即便如此,还应注意广泛测试实现,以确保在写入操作过程中出现失败时文件未损坏。

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

  • 选择 COM 线程模型

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

  • 属性处理程序并发

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

  • 文件并发

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

    文件系统使应用程序能够以某种方式打开文件,从而控制其他应用程序是否可以打开文件。 共享模式支持读取、写入和删除访问权限。 属性系统支持下表中概述的这些共享模式的子集。

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

     

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

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

    有关标志定义,请参阅 GETPROPERTYSTOREFLAGS

了解属性处理程序

使用类型名称

使用属性列表

初始化属性处理程序

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