プレースホルダー ファイルをサポートするクラウド同期エンジンを構築する

同期エンジンとは、通常、リモート ホストとローカル クライアントの間でファイルを同期するサービスです。 Windows 上の同期エンジンは、多くの場合、Windows ファイル システムとエクスプローラーを介してユーザーにこれらのファイルを提示します。 Windows 10 バージョン 1709 より前では、Windows での同期エンジンのサポートは、エクスプローラーのナビゲーション ウィンドウ、Windows システム トレイ、(より技術的なアプリケーション用の) ファイル システム フィルター ドライバーなど、シナリオに依存しないアドホック サーフェスに限定されていました。

Windows 10 バージョン 1709 (Fall Creators Update とも呼ばれます) で、"クラウド ファイル API" が導入されました。 この API は、同期エンジンのサポートを正式化する新しいプラットフォームです。 クラウド ファイル API は、開発者とエンド ユーザーに多くの新しい利点を提供する形で同期エンジンをサポートします。

クラウド ファイル API には、次のネイティブ Win32 API と Windows ランタイム (WinRT) API が含まれています。

  • Cloud Filter API: このネイティブ Win32 API は、ユーザー モードとファイル システムの境界で機能を提供します。 この API は、プレースホルダー ファイルとディレクトリの作成と管理を処理します。
  • Windows.Storage.Provider 名前空間: この WinRT API を使用すると、アプリケーションでクラウド ストレージ プロバイダーを構成し、同期ルートをオペレーティング システムに登録できます。

Note

クラウド ファイル API は現在、UWP アプリでのクラウド同期エンジンの実装をサポートしていません。 クラウド同期エンジンは、デスクトップ アプリに実装する必要があります。

サポートされている機能

クラウド ファイル API には、クラウド同期エンジンを構築するための次の機能が用意されています。

プレースホルダー ファイル

  • 同期エンジンは、ファイルシステム ヘッダーに対して 1 KB のストレージのみを消費し、通常の使用条件下で完全なファイルに自動的にハイドレートするプレースホルダー ファイルを作成できます。 プレースホルダー ファイルは、Windows シェルのアプリおよびエンド ユーザーに対して一般的なファイルとして提示されます。
  • プレースホルダー ファイルは Windows カーネルから Windows シェルまで垂直方向に統合されており、プレースホルダー ファイルとのアプリの互換性は一般に問題にはなりません。 ファイル システム API、コマンド プロンプト、デスクトップまたは UWP アプリのいずれを使用してプレースホルダー ファイルにアクセスする場合でも、ファイルは追加のコード変更なしでハイドレートされ、そのアプリは通常どおりファイルを使用できます。
  • ファイルは、次の 3 つの状態で存在できます。
    • プレースホルダー ファイル: ファイルの空の表現であり、同期サービスが使用可能な場合にのみ利用できます。
    • 完全なファイル: ファイルは暗黙的にハイドレートされており、領域が必要な場合はシステムによって退避される可能性があります。
    • ピン留めされた完全なファイル: ファイルは、エクスプローラーを通じてユーザーによって明示的にハイドレートされており、オフラインで使用できることが保証されています。

次の図は、プレースホルダー、完全、ピン留めされた完全なファイルの状態がエクスプローラーでどのように表示されるかを示しています。

Example of three file states in File Explorer

標準化された同期ルートの登録

  • 同期ルートの登録は簡単で標準化されています。 これには、次のスクリーンショットに示すように、エクスプローラーのナビゲーション ウィンドウでのブランド化されたノードの作成が含まれます。 ルートは、個別の最上位レベルのエントリとして、または親グループの子として作成できます。

    Example of a sync root entry in File Explorer

シェル統合機能

  • 状態アイコン:
    • クラウド ファイル API には、エクスプローラーと Windows デスクトップに表示される標準化された自動ハイドレーション状態アイコンが用意されています。
    • ハイドレーション状態に使用される標準の Windows 状態アイコンに加えて、サービス固有の追加プロパティ用のカスタム状態アイコンを指定できます。
    • レガシ アイコン オーバーレイ シェル拡張を置き換えます。
  • 進行状況の表示:
    • ハイドレートに数秒以上かかるプレースホルダー ファイルを開くと、ハイドレーションの進行状況が表示されます。 進行状況は、コンテキストに応じていくつかの場所に表示されます。
      • コピー エンジンのダイアログ ウィンドウ。
      • インラインの進行状況は、エクスプローラーのファイルの横に表示されます。
      • ファイルがユーザーの具体的な指示で開かれていない場合は、ユーザーに知らせるためのトースト通知が表示され、意図しないハイドレーション アクティビティを制御する方法が提供されます。
  • サムネイルとメタデータ:
    • プレースホルダー ファイルでは、サービスが提供する豊富なサムネイルと拡張ファイル メタデータを使用して、シームレスなエクスプローラー エクスペリエンスをユーザーに提供できます。
  • エクスプローラーのナビゲーション ウィンドウ:
    • クラウド ファイル API を使用して同期ルートを登録すると、同期ルート (のアイコンとカスタム名) がエクスプローラーのナビゲーション ウィンドウに表示されます。
  • エクスプローラーのコンテキスト メニュー:
    • クラウド ファイル API を使用して同期ルートを登録すると、エクスプローラーのコンテキスト メニューに複数の動詞 (メニュー エントリ) が自動的に提供され、ユーザーはファイルのハイドレーション状態を制御できます。
    • デスクトップ ブリッジと互換性のある API を使用して、コンテキスト メニューのこのセクションにさらに動詞を追加できます。
  • ファイル ハイドレーションのユーザー制御:
    • ファイルがユーザーによって明示的にハイドレートされていない場合でも、ユーザーが常にファイルのハイドレートを制御します。 ユーザーに警告し、オプションを提供するために、バックグラウンドのハイドレーションに関する対話型トーストが表示されます。 次の画像は、ファイルのハイドレートのトースト通知を示しています。 Example of an interactive toast shown for background file hydration
    • ユーザーが対話型トーストを使用してアプリによるファイルのハイドレートをブロックした場合、[設定][ファイルの自動ダウンロード] ページでアプリのブロックを解除できます。 Screenshot of the automatic file downloads setting
  • コピー エンジン操作のフック (Windows 10 Insider プレビュー ビルド 19624 以降のバージョンでサポート):
    • クラウド ストレージ プロバイダーは、同期ルート内のファイル操作を監視するためのシェル コピー フックを登録できます。
    • プロバイダーは、同期ルート レジストリ キーの CopyHook レジストリ値を COM ローカル サーバー オブジェクトの CLSID に設定することで、コピー フックを登録します。 このローカル サーバー オブジェクトは、IStorageProviderCopyHook インターフェイスを実装します。
  • ファイル共有 (Windows 11 バージョン 21H2 以降のバージョンでサポート):
    • クラウド ストレージ プロバイダーは、ユーザーが同期ルートの下にあるクラウド ファイルで [共有] コマンドを選択したときに呼び出される共有ハンドラーを登録できます。
    • プロバイダーは、同期ルート レジストリ キーの ShareHandler レジストリ値を COM ローカル サーバー オブジェクトの CLSID に設定することで、共有ハンドラーを登録します。 このローカル サーバー オブジェクトは、IExplorerCommand インターフェイスを実装します。

デスクトップ ブリッジ

  • クラウド ファイル API を使用する同期エンジンは、実装要件としてデスクトップ ブリッジを使用するように設計されています。

CloudMirror サンプル

CloudMirror サンプルは、クラウド ファイル API を使用するソリューションを構築する方法を示しています。 本番環境のコードとして使用するためのものではありません。 信頼性の高いエラー処理は含まれておらず、可能な限り簡単に理解できるように書かれています。 CloudMirror という名前なのは、ローカル ディスク上のローカル フォルダーをミラーするためです。 クラウド ファイル サーバーを表すサーバー フォルダーと、同期ルート パスを指定するクライアント フォルダーを指定します。 最上位ノードが TestStorageProviderDisplayName と呼ばれるエクスプローラー ナビゲーション ウィンドウに表示され、このノードは指定されたクライアント フォルダーにマップされます。

同期に関しては、完全に開発されたクラウド ファイル同期プロバイダーは以下を実装する必要があります。

  • 同期ルート ファイルが単なるプレースホルダーである場合、サービスはハイドレーションのためにファイルの内容をコピーする責任があります。 これはサンプルで実装されています。
  • 同期ルート ファイルが完全なファイルであり、クラウド サービス内のファイルの内容が変更された場合、サービスはローカル同期クライアントに変更を通知し、ローカル同期クライアントは独自の仕様に従ってマージを処理する必要があります。 これはサンプルでは実装されていません。
  • 同期ルート ファイルが完全なファイルであり、同期ルート パス (ローカル クライアント) 内のファイルの内容が変更された場合、ローカル同期クライアントはクラウド サービスに通知し、独自の仕様に従ってマージを処理する必要があります。 ローカル ファイルの変更通知はサンプルに実装されていますが、何も実行しません。

サンプルを使用する

  1. ローカル ハード ドライブに 2 つのフォルダーを作成します。 そのうちの 1 つはサーバーとして機能し、もう 1 つはクライアントとして機能します。
  2. サーバー フォルダーにいくつかのファイルを追加します。 クライアント フォルダーが空であることを確認します。
  3. Visual Studio で CloudMirror サンプルを開きます。 CloudMirrorPackage プロジェクトをスタートアップ プロジェクトとして設定し、サンプルをビルドして実行します。 サンプルのプロンプトが表示されたら、サーバー フォルダーとクライアント フォルダーへの 2 つのパスを入力します。 その後、診断情報を含むコンソール ウィンドウが表示されます。
  4. エクスプローラー開き、TestStorageProviderDisplayName ノードと、サーバー フォルダーにコピーしたすべてのファイルのプレースホルダーが表示されることを確認します。 ピッカーを使用せずにファイルを開こうとするアプリケーションをシミュレートするために、複数のイメージをサーバー フォルダーにコピーします。 そのうちの 1 つを同期ルート フォルダー内でダブルクリックし、ハイドレートされることを確認します。 次に、フォト アプリを開きます。 アプリは隣接するファイルをバックグラウンドで事前に読み込み、ユーザーが他の画像を見るときに遅延がなるべく発生しないようにします。 トーストまたはエクスプローラーでバックグラウンドで退避が発生しているのを確認できます。
  5. エクスプローラーでファイルを右クリックしてコンテキスト メニューを表示し、[TestCommand] メニュー項目が表示されることを確認します。 このメニュー項目をクリックすると、メッセージ ボックスが表示されます。
  6. サンプルを停止するには、コンソール出力にフォーカスを設定し、Ctrl キーと C を押します。 これにより、同期ルートの登録がクリーンアップされ、プロバイダーがアンインストールされます。 サンプルがクラッシュした場合、同期ルートが登録されたままになる可能性があります。 このなると、何かをクリックするたびにエクスプローラーが再起動され、偽のクライアントとサーバーの場所の入力を求められます。 この場合は、コンピューターから CloudMirrorPackage サンプル アプリケーションをアンインストールしてください。

サンプル アーキテクチャ

サンプルは意図的に単純になっています。 インスタンス ポインターを渡す必要が無いように、静的クラスを使用しています。 サンプルのメイン クラスを次に示します。

  • FakeCloudProvider: この最上位クラスは、次のワーカー クラスを制御します。
    • CloudProviderRegistrar: 同期ルート情報を Windows シェルに登録します。
    • Placeholders: 同期ルート パスにプレースホルダー ファイルを生成します。
    • ShellServices: コンテキスト メニュー、サムネイル、およびその他のサービス用の Windows シェル プロバイダーを構築します。
    • CloudProviderSyncRootWatcher: DirectoryWatcher をインスタンス化して同期ルート パスへの変更を監視し、変更に対応します。
    • FileCopierWithProgress: サーバー フォルダーからクライアント フォルダーにファイルをチャンク単位でゆっくりとコピーし、実際のクラウド サーバーからのダウンロードをシミュレートします。 トーストとエクスプローラー UI でユーザーに情報が表示されるように、進行状況を提供します。

上記のクラスに加えて、サンプルには、ユーザーにフォルダーの入力を求めるいくつかのヘルパー クラスといくつかのユーティリティが用意されています。 TestExplorerCommandHandlerCustomStateProviderThumbnailProviderUriSource はすべてシェル サービス プロバイダーの例です。

クラウド ファイル API のアーキテクチャ

クラウド ファイル API のストレージ スタックの中核となるのは、cldflt.sys というファイル システム ミニフィルター ドライバーです。 このドライバーは、ユーザーのアプリケーションと同期エンジンの間のプロキシとして機能します。 同期エンジンは、必要に応じてデータをダウンロードしてアップロードする方法を認識していますが、シェルと連携して、クラウド データがローカルで利用可能であるかのようにファイルを表示するのは cldflt.sys の役目です。

現在、cldflt.sys では NTFS ボリュームのみがサポートされています。NTFS 固有の機能に依存しているためです。

システムには多くのファイル システム ミニフィルター ドライバーがあり、特定のボリュームで同時にアクティブにすることができます。 クラウド ファイル API にとって最も関心のあるドライバーは、ウイルス対策のファイル システム フィルターです。

ファイル システム ミニフィルター ドライバーは、フィルター マネージャーと呼ばれる特殊なカーネル モード コンポーネントによって管理およびサポートされます。 他の多くの処理の中で、フィルター マネージャーは、フィルター メッセージ ポートと呼ばれるコンストラクトを介して、フィルターとユーザー モード コンポーネント間のフィルターなしの通信を容易にします。

ハイドレーション ポリシー

Windows では、さまざまなプライマリ ハイドレーション ポリシーセカンダリ ハイドレーション ポリシーの修飾子がサポートされています。 プライマリ ハイドレーション ポリシーの順序は次のとおりです。

常にフル > フル > プログレッシブ > 部分

アプリケーションと同期エンジンの両方で、優先するプライマリ ハイドレーション ポリシーを定義できます。 指定しない場合、既定のハイドレーション ポリシーは、アプリケーションと同期エンジンの両方でプログレッシブです。

クラウド ファイルのハイドレーション ポリシーは、次の式によってファイルを開く時点で決定されます。

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

たとえば、ユーザーが Fabrikam Cloud Drive に保存されている PDF ファイルを Contoso PDF Viewer を使用して開こうとしているとします。これには、優先ハイドレーション ポリシーが指定されていません。 そのため、アプリケーションのハイドレーション ポリシーはプログレッシブ ハイドレーションになります (この場合は既定)。 ただし、Fabrikam Cloud Drive は完全ハイドレーション同期エンジンであるため、ファイルの最終的なハイドレーション ポリシーは完全ハイドレーションになり、最初のアクセス時にファイルが完全にハイドレートされます。 同期エンジンがプログレッシブ ハイドレーションをサポートしているが、アプリの優先設定が完全ハイドレーションである場合も、同じ結果になります。

ファイルを開いた後は、ファイル ハイドレーション ポリシーを変更できないことに注意してください。

再解析ポイントを使用するアプリケーションとの互換性

クラウド ファイル API は、再解析ポイントを使用してプレースホルダー システムを実装します。 再解析ポイントに関する一般的な誤解は、それらがシンボリック リンクと同じであるという点です。 この誤解がアプリケーションの実装に反映されることがあり、その結果、多くの既存のアプリケーションで再解析ポイントが発生したときにエラーが発生します。

この互換性の問題を軽減するために、クラウド ファイル API では、同期エンジンとメイン イメージが %systemroot% の下に存在するプロセスを除くすべてのアプリケーションに対して常に再解析ポイントを隠蔽します。 再解析ポイントを正しく理解するアプリケーションでは、RtlSetProcessPlaceholderCompatibilityMode または RtlSetThreadProcessPlaceholderCompatibilityMode を使用して、プラットフォームでクラウド ファイル API の再解析ポイントを公開することを強制できます。