プロパティ ハンドラーの登録と配布

このトピックでは、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 Search インデクサーのワーキング セットがこれらのファイルにアクセスしたりインデックスを付けようとしたりするので、メモリ全体に読み込むべきではありません。 詳細については、「 プロパティ ハンドラーの初期化」を参照してください。

    これを実現する便利な手法の 1 つは、次にプロパティ値を書き込む必要がある場合に、ファイル全体を書き換えることなく値を書き込むことができるように、ファイルのヘッダーに余分なスペースを埋め込む方法です。 これには ManualSafeSave 機能が必要です。 この方法では、書き込みの進行中にファイルの書き込み操作が中断される可能性がある追加のリスクが伴いますが (システムクラッシュや電源損失が原因で)、プロパティ サイズは一般的に小さいため、このような中断の可能性も同様に小さく、インプレース プロパティの書き込みによって実現できるパフォーマンスの向上は、この追加のリスクを正当化するのに十分な大きさと見なされます。 それでも、書き込み操作の過程で障害が発生した場合にファイルが破損しないように、実装を広範囲にテストするように注意する必要があります。

    最後に、ManualSafeSave を使用してインプレース プロパティの書き込みを実装する場合、操作をインプレースで実行できない場合があり、ストリーム全体を書き換える必要があります。 書き換えを容易にするために、ハンドラーの初期化中に提供されるストリームでは 、IDestinationStreamFactory インターフェイスが サポートされます。 IDestinationStreamFactory インターフェイスを使用すると、ハンドラー実装で書き込み用の一時的なストリームを取得できます。すべての書き込みが完了し、IDestinationStreamFactory::GetDestinationStream メソッドが呼び出されると、このストリームを使用して元のファイル ストリームが完全に置き換えられます。 コピー先ストリームを使用する場合、元のファイル ストリームは読み取り専用として扱う必要があります。これは、 IDestinationStreamFactory::GetDestinationStream メソッドが呼び出された後に変換先ストリームに置き換えられるためです。

  • COM スレッド モデルの選択

    プロパティ ハンドラーの効率を最大化するには、COM スレッド モデル Bothを使用するように指定する必要があります。 これにより、STA アパートメント (Windows エクスプローラー など) とメッセージ転送エージェント (MTA) アパートメント (Windows Search の SearchProtocolHost プロセスなど) から直接アクセスできるため、これらの環境でのマーシャリングのオーバーヘッドを回避できます。 スレッド モデルの Both 完全な利点を実現するには、ハンドラーが依存するサービスも、 として Both 指定して、これらのコンポーネントの呼び出しでのマーシャリングを回避する必要があります。 これらの特定のサービスのドキュメントを確認して、このスレッド モデルを使用しているかどうかを確認します。

  • プロパティ ハンドラーのコンカレンシー

    プロパティ ハンドラーと IPropertyStore インターフェイスは、同時アクセスではなくシリアル用に設計されています。 Windows エクスプローラー、Windows Search インデクサー、および Windows コードベースからの他のすべてのプロパティ ハンドラー呼び出しでは、この使用が保証されます。 サード パーティがプロパティ ハンドラーを同時に使用する理由はありませんが、この動作を保証することはできません。 また、呼び出しパターンがシリアルであることが想定されている場合でも、呼び出しは異なるスレッドで行われる可能性があります (たとえば、インデクサーで発生するように、オブジェクトが COM RPC を介してリモートで呼び出されている場合など)。 したがって、プロパティ ハンドラーの実装では、異なるスレッドで呼び出されることをサポートする必要があります。また、同時に呼び出されたときに悪影響を受けないようにするのが理想的です。 目的の呼び出しパターンはシリアルであるため、ほとんどの場合、これらの要件を満たすには、クリティカル セクションを使用する簡単な実装で十分である必要があります。 TryEnterCriticalSection 関数を使用して同時呼び出しを検出して失敗させることで、同時呼び出しのブロックを回避できます。

  • ファイルのコンカレンシー

    プロパティ ハンドラーは、複数のアプリケーションが 1 つのファイルに同時にアクセスするシナリオでよく使用されます。 そのため、ハンドラーとアプリケーションは、ファイルを開くときに適切な共有モードを指定してコンカレンシーを管理する必要があります。 また、他のアプリケーションが指定するアクセスを認識し、アクセスが許可されていないケースを管理する必要があります。 すべてのコンシューマーがリベラルな共有モードを指定して他のユーザーが同時にファイルにアクセスできるようにする場合に最適ですが、これを行うときは、整合性の問題を管理する必要があります。 使用する最も適切な共有モードに関する決定は、ファイルにアクセスするアプリケーションのコミュニティのコンテキストで行う必要があります。

    ファイル システムを使用すると、アプリケーションは、他のアプリケーションがファイルを開くことができるかどうかを制御できる方法でファイルを開くことができます。 共有モードでは、読み取り、書き込み、および削除アクセスが有効になります。 プロパティ システムでは、次の表に示すように、これらの共有モードのサブセットがサポートされています。

    アクセス モード 共有モード
    Write 他の読者とライターを拒否する
    Write (EnableShareDenyWrite) 他のリーダーを有効にし、他のライターを拒否する
    読み取り専用 (既定値) 他のリーダーを有効にし、他のライターを拒否する
    読み取り専用 (EnableShareDenyNone) 他のリーダーとライターを有効にする

     

    書き込み用に開いているプロパティ ハンドラー (GPS_READWRITE) は、他のリーダーとライターを拒否します。 ハンドラーは、登録でフラグ (読み取りを有効にする) を EnableShareDenyWrite 指定することで、リーダーを有効にする動作をオプトインできます。

    プロパティ ハンドラーは 読み取り (GPS_DEFAULT) 用に開きます。既定では、他のリーダーは有効になりますが、他のライターは拒否されます。 ハンドラーは、登録で フラグを指定することで、他のライターを EnableShareDenyNone 有効にすることを選択できます。 これは、ハンドラーがファイルの読み取り中にファイルの内容が変更される状況をハンドラーが正常に処理できることを意味します。

    フラグ定義については、「 GETPROPERTYSTOREFLAGS」を参照してください。

プロパティ ハンドラーについて

種類名の使用

プロパティ リストの使用

プロパティ ハンドラーの初期化

プロパティ ハンドラーのベスト プラクティスと FAQ