繁体   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