簡體   English   中英

使用我的縮略圖提供程序后,資源管理器不會釋放文件

[英]Explorer Wont Release Files After Using My Thumbnail Provider

我已經為文件類型設置了縮略圖提供程序。

該項目是與

  • C#
  • .NET 4.5

我正在運行Windows x64

我的提供者可以按預期成功生成縮略圖,並且我可以移動,刪除,復制和提取文件。 鎖定問題似乎是由於文件放在文件夾中引起的。 此時,移動,刪除等文件夾均顯示錯誤“文件正在使用”。

如果您熟悉Explore,請確認已使用Sysinternal的Process Explorer鎖定了該文件。

我嘗試了2種方法來解決此問題...

  1. 我自己實現了IThumbnailProviderIInitializeWithStream
  2. 二手3rd party Sharpshell

兩者都遭受相同的問題,文件沒有被釋放。

在Sharpshell的github上,也已經開始指定此問題。 https://github.com/dwmkerr/sharpshell/issues/78

我像這樣將文件類型關聯到注冊表中

HKEY_CLASSES_ROOT
---- .qb
      ----shellex
          ----{e357fccd-a995-4576-b01f-234630154e96} : my CLSID...

我也嘗試過...

HKEY_CLASSES_ROOT
---- .qb
     -----PersistentHandler : my CLSID...

兩者都會導致創建此問題。

如果我改為實現IExtractImage ,是否會遇到相同的問題?

我知道不“正式”支持C#這樣做,這是我的問題所在嗎? 如果我要用C ++來實現這一點,我會遇到同樣的問題嗎?

編輯:

我想提一下文件似乎在1分鍾后被釋放,並且一切恢復正常。

縮略圖創建

一些字節被讀入緩沖區...然后從中生成圖像。

public void GetThumbnail(int cx, out IntPtr hBitmap, out WTS_ALPHATYPE   bitmapType)
{
    ... bunch of other code
    using (MemoryStream steam = new MemoryStream(buffer))
    using (var image = new Bitmap(steam))
    using (var scaled = new Bitmap(image, cx, cx))
    {
        hBitmap = scaled.GetHbitmap();
        hBitmap = (IntPtr)(hBitmap.ToInt64());
    }
}

編輯2:

做一些更多的測試,我調用了DeleteObject(hBitmap)(即使這會破壞縮略圖),並且文件仍然被鎖定。 我什至從GetThumbnail刪除了所有代碼...只是給出了相同的結果,文件已鎖定。 還有更多的事情嗎?

原來,您需要釋放從IInitializeWithStream獲得的COM IStream對象。

通過閱讀有關處置COM對象的更多信息,我得出了這個結論。

釋放COM對象的正確方法?

我按照MS的示例介紹如何包裝IStream

https://msdn.microsoft.com/en-us/library/jj200585%28v=vs.85%29.aspx

  public class StreamWrapper : Stream { private IStream m_stream; // initialize the wrapper with the COM IStream public StreamWrapper(IStream stream) { if (stream == null) { throw new ArgumentNullException(); } m_stream = stream; } // .... bunch of other code protected override void Dispose(bool disposing) { if (m_stream != null) { Marshal.ReleaseComObject(m_stream); // releases the file m_stream = null; } } } 

這是一個樣本。

點擊上面的鏈接,查看StreamWrapper的實現...

[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
[ProgId("mythumbnailer.provider"), Guid("insert-your-guid-here")]
public class QBThumbnailProvider : IThumbnailProvider, IInitializeWithStream
{
    #region IInitializeWithStream

    private StreamWrapper stream{ get; set; }

    public void Initialize(IStream stream, int grfMode)
    {
        // IStream passed to our wrapper which handles our clean up
        this.stream = new StreamWrapper(stream);
    }

    #endregion

    #region IThumbnailProvider

    public void GetThumbnail(int cx, out IntPtr hBitmap, out WTS_ALPHATYPE bitmapType)
    {
        hBitmap = IntPtr.Zero;
        bitmapType = WTS_ALPHATYPE.WTSAT_ARGB;

        try
        {
            //... bunch of other code

            // set the hBitmap somehow
            using (MemoryStream stream = new MemoryStream(buffer))
            using (var image = new Bitmap(stream))
            using (var scaled = new Bitmap(image, cx, cx))
            {
                hBitmap = scaled.GetHbitmap();
            }
        }
        catch (Exception ex)
        {
        }

        // release the IStream COM object
        stream.Dispose();
    }
    #endregion
}

基本上可以歸結為兩行代碼

Marshal.ReleaseComObject(your_istream); // releases the file
your_istream = null;

邊注

使用scaled.GetHbitmap();創建的GDI位圖scaled.GetHbitmap(); 可能需要處理,但是我找不到不丟失創建的縮略圖的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM