現在,.NET CLR 4.0支持並行(SxS)操作,現在應該可以在託管代碼中編寫shell 擴展。我已經嘗試過,併成功編寫了一個Property Handler ,它們實現了IPropertyStore,IInitializeWithStream和IPropertyStoreCapabilities。什麼是實施託管屬性處理程序外殼擴展的正確方法?
處理程序 工作正常,並通過瀏覽瀏覽文件時,如預期的那樣叫。在預覽面板和文件屬性「詳細信息」面板中顯示 自定義屬性時,它也可以正常工作。
然而,當我試圖 編輯在預覽面板中的屬性,然後單擊「保存」我得到一個「文件正在使用」錯誤,指出 文件在Windows資源管理器打開。
一些花絮:
- 當Explorer調用IInitializeWithStream.Initialize的STGM屬性設置爲STGM_SHARE_DENY_WRITE。
- 並且在任何時候瀏覽器都不會調用IPropertyStore.SetValue或IPropertyStore.Commit。
- 我看到在不同線程上我的處理程序對相同文件屬性的重複調用。
那麼,我需要更改(或設置在registery)以獲得屬性保存工作?
更新:
感謝奔我找到了工作。 「困難的部分」(至少對我來說)是理解COM互操作將永遠不會在我的PropertyHandler上調用Dispose或Finalize。這將我打開的文件一直打開,直到GC運行。幸運的是,「屬性處理程序協議」的工作原理是當爲ReadValue()調用IInitializeWithSream.Initialize()時,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;
}
沒有預覽處理程序,但Windows搜索服務似乎偶爾會加載處理程序。但它不應該鎖定文件?此外,我可以通過切換到使用IInitializeWithFile進行編輯工作,並按預期方式調用SaveValue()和Commit()。 無論如何,即使當我剔除IInitializeWithStream以便它從不使用流(並且GetValue()返回默認空值)時,編輯屬性時它仍然會出現相同的錯誤。 Explorer甚至不會調用SaveValue()或Commit()。 – 2010-07-13 03:11:18
我是否需要AddRef()我在Initialize()中獲得的IStream?然後在Commit()之後釋放()它?我曾假設我沒有。 根據你最近的一期,我認爲在並排模式下使用.NET 4.0解決了shell擴展的CLR版本問題。我已經驗證了正確的CLR正在運行我的代碼。 – 2010-07-13 03:11:37