5

.NET CLR 4.0 がサイド バイ サイド (SxS) 操作をサポートするようになったので、マネージ コードでシェル拡張機能を記述できるようになりました。私はこれを試み、IPropertyStore、IInitializeWithStream、および IPropertyStoreCapabilities を実装するプロパティ ハンドラーのコーディングに成功しました。

ハンドラーは正常に動作し、エクスプローラーを介してファイルを参照するときに期待どおりに呼び出されます。また、プレビュー パネルとファイル プロパティの「詳細」パネルにカスタム プロパティを表示する際にも問題なく動作します。

しかし、プレビュー パネルでプロパティを編集しようとして [保存] をクリックすると、ファイルが Windows エクスプローラーで開かれていることを示す「ファイルは使用中です」というエラーが表示されます。

いくつかのヒント:

  1. エクスプローラーが IInitializeWithStream.Initialize を呼び出すと、STGM プロパティが STGM_SHARE_DENY_WRITE に設定されます。
  2. そして、エクスプローラーが IPropertyStore.SetValue または IPropertyStore.Commit を呼び出すことはありませんでした。
  3. 同じファイル プロパティに対して、異なるスレッドでハンドラが繰り返し呼び出されています。

では、プロパティの保存を機能させるには、何を変更 (またはレジストリに設定) する必要がありますか?

アップデート:

ベンのおかげでうまくいきました。「難しい部分」(少なくとも私にとって) は、COM 相互運用が PropertyHandler で Dispose または Finalize を呼び出すことは決してないことを理解することでした。これは、GC が実行されるまで、処理したファイルを開いたままにしていました。

幸いなことに、「プロパティ ハンドラー プロトコル」は、IInitializeWithSream.Initialize() が ReadValue() に対して呼び出されると、streamMode が ReadOnly になり、SetValue() に対して呼び出されると、streamMode が ReadWrite になり、Commit() が呼び出されるように機能します。最後に。

int IInitializeWithStream.Initialize( IStream stream, uint grfMode )
{
    _stream = stream;
    _streamMode = (Stgm)grfMode;

    Load();

    // We release here cause if this is a read operation we won't get called back, 
    // and our finializer isn't called. 
    if ( ( _streamMode & Stgm.ReadWrite ) != Stgm.ReadWrite )
    {
        Marshal.ReleaseComObject( _stream );
        _stream = null;
    }
    return HResult.S_OK;
}

int IPropertyStore.Commit()
{
    bool result = false;

    if ( _stream != null )
    {
        result = WriteStream( _stream );
        Marshal.ReleaseComObject( _stream );
        _stream = null;
    }

    return result ? HResult.S_OK : HResult.E_FAIL;
}
4

2 に答える 2

3

Yes, you have to AddRef() the stream to keep it open and to keep the reference alive correctly.

Note that the indexer will use your property handler to open the file as well. So if you leak the stream object, the file will remain open. You can use the sysinternals procexp to tell what process has the file open, or procmon to tell what calls and parameters it used.

于 2010-07-13T04:23:04.277 に答える
1

エクスプローラーは、ファイルを開いている可能性のある他のアプリケーションに干渉しないようにします。ファイルが別のアプリケーションによって合法的に使用されている可能性はありますか? プレビュー ハンドラーが開いていますか?

ストリームを必要以上に長く開いたままにするプロパティ ハンドラー (または制限付きのアクセス許可でファイルを開くファイル ベースのハンドラー) が時々見られます。タイムリーにストリームをリリースしているかどうかを確認できますか?

最後に、これは差し迫った問題とは関係ないと思いますが、.NET シェル拡張機能の使用はサポートされていません。これをどの製品にも組み込まないことをお勧めします。

-ベン

于 2010-07-13T01:32:02.433 に答える