IFileIsInUse
COM公式ドキュメント
別のアプリケーションによって使用中のファイルに関する情報を取得したり、そのファイルを閉じたりするために呼び出せるメソッドを公開します。
解説(Remarks)
Windows Vista より前のバージョンの Windows では、ユーザーが別のアプリケーションで開かれているファイルにアクセスしようとすると、そのファイルが既に開かれている旨のメッセージを示すダイアログ ボックスが表示されるだけでした。このメッセージはユーザーに他方のアプリケーションを閉じるよう促すものでしたが、そのアプリケーションを特定するものではありませんでした。この提案以外に、ダイアログ ボックスには状況に対処するためのユーザー操作は用意されていませんでした。このインターフェイスは、ユーザーが直接操作を行えるより有益なダイアログ ボックスにつながるメソッドを提供します。
実行中オブジェクト テーブル (Running Object Table)
アプリケーションがファイルを開くとき、そのアプリケーションはインスタンス化した IFileIsInUse オブジェクトを実行中オブジェクト テーブル (ROT) に挿入することでファイルを登録します。ROT は現在実行中のオブジェクトを追跡する、グローバルにアクセス可能な参照テーブルです。これらのオブジェクトはモニカーによって識別できます。クライアントがモニカーをオブジェクトにバインドしようとすると、モニカーは ROT を確認してそのオブジェクトが既に実行中かどうかを判断します。これにより、モニカーは新しいインスタンスを読み込むのではなく、現在のインスタンスにバインドできます。ファイルを ROT に追加するには、次の手順を実行します。
- GetRunningObjectTable 関数を呼び出して、IRunningObjectTable のインスタンスを取得します。
- 現在使用中のファイルに対して IFileIsInUse オブジェクトを作成します。
- 現在使用中のファイルに対して IMoniker オブジェクトを作成します。
- IRunningObjectTable::Register を呼び出して、IFileIsInUse オブジェクトと IMoniker オブジェクトを ROT に挿入します。
Register の呼び出しでは、ROTFLAGS_ALLOWANYCLIENT フラグを指定します。これにより、ROT エントリがセキュリティ境界を越えて機能できるようになります。このフラグを使用するには、呼び出し元のアプリケーションが明示的なアプリケーション ユーザー モデル ID (AppUserModelID) (System.AppUserModel.ID) を持っている必要があります。明示的な AppUserModelID があると、コンポーネント オブジェクト モデル (COM) はアプリケーションのセキュリティ設定を検査できます。明示的な AppUserModelID なしで ROTFLAGS_ALLOWANYCLIENT を指定して Register を呼び出そうとすると失敗します。ROTFLAGS_ALLOWANYCLIENT フラグなしで Register を呼び出すこともでき、その場合アプリケーションは正しく動作しますが、自身のセキュリティ レベル内に限られます。
Register メソッドの [out] パラメーターで取得される値は、後で ROT からエントリを取得または削除する呼び出しで、そのエントリを識別するために使用されます。
実装するタイミング
他のアプリケーションで開くことができるファイルの種類を開くアプリケーションは、IFileIsInUse を実装する必要があります。アプリケーションがこのインターフェイスを実装すると、Windows エクスプローラーが共有エラーの発生元を検出できるようになり、その結果、ユーザーはこれらのエラーが原因で失敗した操作に対処して再試行できるようになります。使用するタイミング
アプリケーションは、共有エラーを解決するために他のアプリケーションと通信する目的で IFileIsInUse を呼び出します。これらのエラーは、ファイル システムに対するユーザー操作に応じて発生します。たとえば、あるフォルダー内のファイルがアプリケーションで開かれている状態で、ユーザーがそのフォルダーの名前を変更しようとすると、名前変更操作は失敗します。Windows エクスプローラーはそのアプリケーションの IFileIsInUse 実装を呼び出して、ユーザーが競合を特定し、この問題を解決できるよう支援できます。サンプル
IFileIsInUse を実装してファイルを ROT に登録する方法を示す、File Is in Use サンプルを参照してください。このサンプルでは続いて、アプリケーションで現在開かれているファイルについて追加情報とオプションを表示するために、File In Use ダイアログをカスタマイズする方法を示します。メソッド 5
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
ファイルを使用しているアプリケーションの名前を取得します。
| ppszName | LPWSTR* | out | バッファーへのポインターのアドレス。このメソッドが正常に終了すると、そのバッファーがアプリケーション名を受け取ります。 |
戻り値
型: HRESULT
このメソッドが成功した場合は S_OK を返します。それ以外の場合は HRESULT エラー コードを返します。
解説(Remarks)
この情報はダイアログ ボックスでユーザーに提示でき、ユーザーが競合の発生元を把握して適切に対応できるようにします。たとえば「File.txt は Litware によって使用中です」のように表示します。
使用中のファイルがどのように使用されているかを示す値を取得します。
| pfut | FILE_USAGE_TYPE* | out | 値へのポインター。このメソッドが正常に終了すると、この値は FILE_USAGE_TYPE 値のいずれかを受け取ります。 |
戻り値
型: HRESULT
このメソッドが成功した場合は S_OK を返します。それ以外の場合は HRESULT エラー コードを返します。
ファイルを閉じることができるかどうか、および UI がファイルを使用しているアプリケーションのウィンドウに切り替えられるかどうかを判定します。
| pdwCapFlags | DWORD* | out | 値へのポインター。このメソッドが正常に終了すると、この値は機能フラグを受け取ります。次の値のいずれか一方または両方です。 OF_CAP_CANSWITCHTO (0x0001)0x0001。UI は、ファイルを使用しているアプリケーションの最上位ウィンドウに切り替えられます。 OF_CAP_CANCLOSE (0x0002)0x0002。ファイルを閉じることができます。 |
戻り値
型: HRESULT
このメソッドが成功した場合は S_OK を返します。それ以外の場合は HRESULT エラー コードを返します。
解説(Remarks)
このメソッドが返す機能は、共有の競合をユーザーに知らせるために表示するダイアログ ボックスの構成に使用できます。たとえば、OF_CAP_CANSWITCHTO フラグが取得された場合は、競合しているアプリケーションのウィンドウ (IFileIsInUse::GetSwitchToHWND によって取得される HWND 情報に基づく) にユーザーを切り替えるボタンをダイアログ ボックスに追加でき、ユーザーが状況に応じて適切に対処できるようにします。OF_CAP_CANCLOSE フラグが取得された場合は、CloseFile メソッドを呼び出す 閉じる ボタンをダイアログ ボックスに表示できます。
ファイルを使用しているアプリケーションの最上位ウィンドウのハンドルを取得します。
| phwnd | HWND* | out | HWND 値へのポインター。このメソッドが正常に終了すると、この値はウィンドウ ハンドルを受け取ります。 |
戻り値
型: HRESULT
このメソッドが成功した場合は S_OK を返します。それ以外の場合は HRESULT エラー コードを返します。
解説(Remarks)
機能フラグ OF_CAP_CANSWITCHTO を返すファイルのみが切り替え可能です。
現在使用中のファイルを閉じます。
戻り値
型: HRESULT
このメソッドが成功した場合は S_OK を返します。それ以外の場合は HRESULT エラー コードを返します。
解説(Remarks)
機能フラグ OF_CAP_CANCLOSE を返すファイルのみが、このメソッドで閉じることができます。このフラグが返された場合は、このメソッドを呼び出す 閉じる オプションを含むダイアログ ボックスをユーザーに表示できます。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IFileIsInUse "{64A1CBF0-3A1A-4461-9158-376969693950}" #usecom global IFileIsInUse IID_IFileIsInUse "{}" #comfunc global IFileIsInUse_GetAppName 3 var #comfunc global IFileIsInUse_GetUsage 4 var #comfunc global IFileIsInUse_GetCapabilities 5 var #comfunc global IFileIsInUse_GetSwitchToHWND 6 sptr #comfunc global IFileIsInUse_CloseFile 7 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IFileIsInUse "{64A1CBF0-3A1A-4461-9158-376969693950}" #usecom global IFileIsInUse IID_IFileIsInUse "{}" #comfunc global IFileIsInUse_GetAppName 3 sptr #comfunc global IFileIsInUse_GetUsage 4 sptr #comfunc global IFileIsInUse_GetCapabilities 5 sptr #comfunc global IFileIsInUse_GetSwitchToHWND 6 sptr #comfunc global IFileIsInUse_CloseFile 7 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。