我为文件类型设置了缩略图提供程序。
该项目是用
制作的我正在运行Windows x64
我的提供商按预期成功生成了缩略图,我可以移动,删除,复制等文件。锁定问题似乎是由文件放在文件夹中引起的。此时,移动,删除等文件夹都显示错误“正在使用文件”。
我已经确认使用Sysinternal的Process Explorer锁定文件,如果您熟悉它。
我尝试了两种尝试解决此问题的方法......
IThumbnailProvider
和IInitializeWithStream
。两者都遭遇同样的问题,文件没有被释放。
在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
中删除了所有代码...只是给出相同的结果,文件已锁定。还有什么事情要继续吗?
答案 0 :(得分:1)
原来你需要释放从IInitializeWithStream
获得的COM IStream对象。
通过阅读有关处理COM对象的更多信息,我得出了这个结论。
Proper way of releasing COM objects?
我按照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位图可能需要处理,但我无法在不丢失创建的缩略图的情况下找到方法。