2010-07-08 22 views
5

現在,.NET CLR 4.0支持並行(SxS)操作,現在應該可以在託管代碼中編寫shell 擴展。我已經嘗試過,併成功編寫了一個Property Handler ,它們實現了IPropertyStore,IInitializeWithStream和IPropertyStoreCapabilities。什麼是實施託管屬性處理程序外殼擴展的正確方法?

處理程序 工作正常,並通過瀏覽瀏覽文件時,如預期的那樣叫。在預覽面板和文件屬性「詳細信息」面板中顯示 自定義屬性時,它也可以正常工作。

然而,當我試圖 編輯在預覽面板中的屬性,然後單擊「保存」我得到一個「文件正在使用」錯誤,指出 文件在Windows資源管理器打開。

一些花絮:

  1. 當Explorer調用IInitializeWithStream.Initialize的STGM屬性設置爲STGM_SHARE_DENY_WRITE。
  2. 並且在任何時候瀏覽器都不會調用IPropertyStore.SetValue或IPropertyStore.Commit。
  3. 我看到在不同線程上我的處理程序對相同文件屬性的重複調用。

那麼,我需要更改(或設置在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; 
} 

回答

3

是的,你必須的AddRef()流,以保持它的開放和保持準確的參考活着。

請注意,索引器將使用您的屬性處理程序來打開文件。所以如果你泄漏流對象,文件將保持打開狀態。您可以使用sysinternals procexp來告訴哪個進程打開了文件,或者procmon告訴它使用了哪些調用和參數。

1

Explorer試圖確保它不會干擾可能打開文件的其他應用程序。該文件是否可以被其他應用程序合法使用?預覽處理程序是否打開?

有時,我們會看到屬性處理程序將其流保持打開時間超過所需時間(或基於文件的處理程序以限制性權限打開文件)。您能否驗證您是否及時發佈了流?

最後,我不認爲這與您的直接問題有關,但使用.NET外殼擴展不受支持。我們建議您不要將其納入任何產品。

-Ben

+0

沒有預覽處理程序,但Windows搜索服務似乎偶爾會加載處理程序。但它不應該鎖定文件?此外,我可以通過切換到使用IInitializeWithFile進行編輯工作,並按預期方式調用SaveValue()和Commit()。 無論如何,即使當我剔除IInitializeWithStream以便它從不使用流(並且GetValue()返回默認空值)時,編輯屬性時它仍然會出現相同的錯誤。 Explorer甚至不會調用SaveValue()或Commit()。 – 2010-07-13 03:11:18

+0

我是否需要AddRef()我在Initialize()中獲得的IStream?然後在Commit()之後釋放()它?我曾假設我沒有。 根據你最近的一期,我認爲在並排模式下使用.NET 4.0解決了shell擴展的CLR版本問題。我已經驗證了正確的CLR正在運行我的代碼。 – 2010-07-13 03:11:37

相關問題