生成支持占位符文件的云同步引擎

同步引擎是一种用于(通常在远程主机和本地客户端之间)同步文件的服务。 Windows 上的同步引擎通常通过 Windows 文件系统和文件资源管理器向用户呈现这些文件。 在 Windows 10 版本 1709 之前,Windows 中的同步引擎支持仅限于与场景无关的临时界面,例如文件资源管理器的导航窗格、Windows 系统托盘和(对于更多技术应用程序)文件系统筛选器驱动程序。

Windows 10 版本 1709(也称为 Fall Creators Update)引入了云文件 API。 此 API 是正式支持同步引擎的新平台。 云文件 API 提供对同步引擎的支持,为开发人员和最终用户带来许多新的好处。

云文件 API 包含以下本机 Win32 API 和 Windows 运行时 (WinRT) API:

  • 云筛选器 API:此本机 Win32 API 在用户模式和文件系统之间的边界提供功能。 此 API 处理占位符文件和目录的创建和管理。
  • Windows.Storage.Provider 命名空间:此 WinRT API 使应用程序能够配置云存储提供程序,并将同步根注册到操作系统。

注意

云文件 API 目前不支持在 UWP 应用中实现云同步引擎。 云同步引擎必须在桌面应用中实现。

支持的功能

云文件 API 提供以下用于生成云同步引擎的功能。

占位符文件

  • 同步引擎可以创建占位符文件,这样的占位符文件仅消耗 1 KB 的文件系统标头存储空间,并且在正常使用的情况下自动水化为完整文件。 占位符文件在 Windows Shell 中作为典型文件呈现给应用程序和最终用户。
  • 占位符文件从 Windows 内核一直到 Windows Shell 都是垂直集成的,并且应用程序与占位符文件的兼容性通常不是问题。 无论你是使用文件系统 API、命令提示符还是桌面或 UWP 应用来访问占位符文件,文件都会水化,而无需你进行额外的代码更改,并且该应用可以正常使用此文件。
  • 文件能够以三种状态存在:
    • 占位符文件:文件的空表示形式,仅当同步服务可用时才可用。
    • 完整文件:文件已隐式水化,如果需要空间,系统可能会将其脱水。
    • 固定的完整文件:文件已由用户通过文件资源管理器显式水化,并保证脱机可用。

下图演示占位符文件、完整文件和固定的完整文件状态在文件资源管理器中如何显示。

Example of three file states in File Explorer

标准化同步根注册

  • 注册同步根目录非常简单且标准化。 这包括在文件资源管理器的导航窗格中创建品牌节点,如以下屏幕截图所示。 根可以创建为单个顶级条目,也可以创建为父分组的子级。

    Example of a sync root entry in File Explorer

Shell 集成

  • 状态图标:
    • 云文件 API 提供在文件资源管理器和 Windows 桌面中显示的标准化自动水化状态图标。
    • 除了用于水化状态的标准 Windows 状态图标外,还可以为其他特定于服务的属性提供自定义状态图标。
    • 替换旧图标覆盖 Shell 扩展。
  • 进度指示:
    • 打开需要几秒钟以上的时间才能水化的占位符文件时,将会显示水化进度。 进度显示在多个位置,具体取决于上下文:
      • 在复制引擎对话框窗口中。
      • 内联进度显示在文件资源管理器中的文件旁边。
      • 如果文件未在用户发出特定指令时打开,则会显示一条 toast 通知,以便通知用户并提供一种用于控制意外水化活动的方式。
  • 缩略图和元数据:
    • 占位符文件可具有服务提供的丰富缩略图和扩展文件元数据,从而为用户提供无缝的文件资源管理器体验。
  • 文件资源管理器导航窗格:
    • 将同步根注册到云文件 API 会导致该同步根(带有图标和自定义名称)显示在文件资源管理器的导航窗格中。
  • 文件资源管理器上下文菜单:
    • 将同步根注册到云文件 API 会自动在文件资源管理器的上下文菜单中提供多个谓词(菜单条目),以便让用户控制其文件的水化状态。
    • 可以使用桌面桥兼容的 API 将其他谓词添加到上下文菜单的此部分。
  • 用户对文件水化的控制:
    • 用户始终可以控制文件水化,即使文件未由该用户显式水化也是如此。 将会显示一个用于执行后台水化的交互式 toast,以便提醒用户并提供选项。 下图演示了有关一个正在水化的文件的 toast 通知。 Example of an interactive toast shown for background file hydration
    • 如果用户通过交互式 toast 阻止了某个应用将文件水化,他们可以在“设置”的“自动文件下载”页中取消阻止该应用。 Screenshot of the automatic file downloads setting
  • 挂钩复制引擎操作(在 Windows 10 Insider Preview 版本 19624 及更高版本中受支持):
    • 云存储提供程序可以注册 shell 副本挂钩,以监视其同步根中的文件操作。
    • 该提供程序通过将其同步根注册表项下的 CopyHook 注册表值设置为其 COM 本地服务器对象的 CLSID 来注册其复制挂钩。 此本地服务器对象实现 IStorageProviderCopyHook 接口。
  • 文件共享(在 Windows 11 版本 21H2 及更高版本中受支持):
    • 云存储提供程序可以注册一个要在用户对其同步根下的云文件选择“共享”命令时调用的共享处理程序。
    • 该提供程序通过将其同步根注册表项下的 ShareHandler 注册表值设置为其 COM 本地服务器对象的 CLSID 来注册其共享处理程序。 此本地服务器对象实现 IExplorerCommand 接口。

桌面桥

  • 使用云文件 API 的同步引擎已设计为将桌面桥用作一个实现要求。

云镜像示例

云镜像示例演示如何生成使用云文件 API 的解决方案。 它不适合用作生产代码。 它缺少可靠的错误处理,并且编写为尽可能容易理解。 它称为“云镜像”,因为它只是镜像本地磁盘上的本地文件夹。 你需要指定一个用于表示云文件服务器的服务器文件夹和一个用于指定同步根路径的客户端文件夹。 文件资源管理器的导航窗格中会出现一个名为 TestStorageProviderDisplayName 的顶级节点,该节点映射到指定的客户端文件夹。

在同步方面,成熟的云文件同步提供程序必须实现以下功能:

  • 当同步根文件只是占位符时,该服务负责复制文件的内容以进行水化。 这已在该示例中实现。
  • 当同步根文件是完整文件并且云服务中文件的内容发生更改时,该服务负责向本地同步客户端通知此更改,并且本地同步客户端必须根据自己的规范处理合并。 这未在该示例中实现。
  • 当同步根文件是完整文件并且同步根路径(本地客户端)中文件的内容发生更改时,本地同步客户端必须通知云服务并根据自己的规范处理合并。 本地文件更改通知已在该示例中实现,但它不执行任何操作。

使用本示例

  1. 在本地硬盘驱动器上创建两个文件夹。 其中一个将充当服务器,另一个充当客户端。
  2. 将某些文件添加到服务器文件夹。 确保客户端文件夹为空。
  3. 在 Visual Studio 中打开云镜像示例。 将 CloudMirrorPackage 项目设置为启动项目,然后生成并运行该示例。 当该示例提示时,输入两个分别指向服务器和客户端文件夹的路径。 在此之后,你将看到一个包含诊断信息的控制台窗口。
  4. 打开文件资源管理器,并确认看到 TestStorageProviderDisplayName 节点以及你复制到服务器文件夹中的所有文件的占位符。 若要模拟一个尝试在不使用选取器的情况下打开文件的应用程序,请将多个图片复制到服务器文件夹。 在同步根文件夹中双击其中一个图片,确认其水化。 然后,打开“照片”应用。 该应用将在后台预加载相邻文件,以使用户在浏览其他图片时不太可能遇到延迟。 可以通过 toast 或文件资源管理器观察后台脱水情况。
  5. 右键单击文件资源管理器中的文件以显示上下文菜单,并确认看到 TestCommand 菜单项。 单击此菜单项将显示消息框。
  6. 若要停止该示例,请将焦点设置为控制台输出,然后按 Ctrl-C。 这将清理同步根注册,以便卸载提供程序。 如果该示例崩溃,同步根可能会保持已注册状态。 这将导致每次单击任何内容时都会重新启动文件资源管理器,并且系统会提示你输入虚假客户端和服务器的位置。 如果发生这种情况,请从计算机中卸载 CloudMirrorPackage 示例应用程序。

示例体系结构

此示例是有意编写得简单的。 它使用静态类,这样就无需传递实例指针。 下面是示例中的主类:

  • FakeCloudProvider:此顶级类控制以下辅助角色类:
    • CloudProviderRegistrar:向 Windows Shell 注册同步根信息。
    • Placeholders:在同步根路径中生成占位符文件。
    • ShellServices:为上下文菜单、缩略图和其他服务构造 Windows Shell 提供程序。
    • CloudProviderSyncRootWatcher:实例化 DirectoryWatcher 以监视同步根路径的更改并根据更改执行操作。
    • FileCopierWithProgress:将文件以块形式从服务器文件夹缓慢复制到客户端文件夹,从而模拟从真正的云服务器下载这些文件。 提供进度指示,以便 toast 和文件资源管理器 UI 向用户显示一些信息。

除了上述类,该示例还提供多个帮助器类来提示用户输入文件夹和一些实用工具。 TestExplorerCommandHandler、CustomStateProvider、ThumbnailProvider 和 UriSource 都是 Shell 服务提供商的示例。

云文件 API 体系结构

云文件 API 中存储堆栈的核心是一个名为 cldflt.sys 的文件系统微筛选器驱动程序。 此驱动程序充当用户应用程序和同步引擎之间的代理。 同步引擎知道如何按需下载和上传数据,而 cldflt.sys 负责使用 Shell 来显示文件,就像云数据在本地可用一样。

Cldflt.sys 目前仅支持 NTFS 卷,因为它依赖于 NTFS 特有的某些功能。

系统中有许多文件系统微筛选器驱动程序,它们可以同时在一个给定卷上处于活动状态。 云文件 API 最感兴趣的驱动程序是防病毒文件系统筛选器。

文件系统微筛选器驱动程序受一个称为“筛选器管理器”的特殊内核模式组件管理和支持。 除了许多其他职责外,筛选器管理器还通过一个称为“筛选器消息端口”的构造来促进筛选器和用户模式组件之间未筛选的通信。

水化策略

Windows 支持各种主要水化策略辅助水化策略修改程序。 主要水化策略具有以下顺序:

始终完全 > 完全 > 渐进式 > 部分

应用程序和同步引擎都可以定义其首选的主要水化策略。 如果未指定,则应用程序和同步引擎的默认水化策略是渐进式的。

云文件的水化策略在文件打开时通过以下公式确定:

File hydration policy = max(app hydration policy, provider hydration policy)

例如,假设用户尝试使用 Contoso PDF 查看器打开存储在 Fabrikam Cloud Drive 上的 PDF 文件,而该查看器未指定首选水化策略。 因此,应用程序水化策略在这种情况下默认为渐进式水化。 但是,由于 Fabrikam Cloud Drive 是一个完全水化同步引擎,因此文件上的最终水化策略将变为“完全水化”,这将导致文件在第一次访问时完全水化。 如果同步引擎支持渐进式水化,但应用的首选项是完全水化,则会出现相同的结果。

请注意,打开文件后,文件水化策略将无法更改。

与使用重新分析点的应用程序的兼容性

云文件 API 使用重新分析点实现占位符系统。 对重新分析点的常见误解是它们与符号链接相同。 这种误解偶尔反映在应用程序实现中,因此,许多现有应用程序在遇到任何重新分析点时都会出错。

为了缓解此兼容性问题,云文件 API 始终对除了主映像位于 %systemroot% 下的同步引擎和进程外的所有应用程序隐藏其重新分析点。 正确理解重新分析点的应用程序可以使用 RtlSetProcessPlaceholderCompatibilityModeRtlSetThreadProcessPlaceholderCompatibilityMode 强制平台公开云文件 API 的重新分析点。