我继承了以下扩展方法,该方法基于文件路径
创建ImageSource对象public static class ImageSourceExtensions
{
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0;
[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
public static ImageSource GetIconFromFolder(this string filePath)
{
SHFILEINFO shinfo = new SHFILEINFO();
SHGetFileInfo(filePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo),
SHGFI_ICON | SHGFI_LARGEICON);
using (Icon i = Icon.FromHandle(shinfo.hIcon))
{
//Convert icon to a Bitmap source
ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
i.Handle,
new Int32Rect(0, 0, i.Width, i.Height),
BitmapSizeOptions.FromEmptyOptions());
return img;
}
}
}
此扩展方法适用于文件夹和文件3310次。在第3311个方法调用上,抛出以下异常:
'传递给Icon的Win32句柄无效或错误 类型“
使用 shinfo.hIcon 属性时会抛出此错误。
错误最初是在我的主应用程序中引发的,每次都在不同的文件上。我已经将这个类提取到一个新项目中,并且可以通过在单击按钮上执行此操作来获得相同的错误(在相同的次数之后):
String path = @"C:\Generic Folder\Generic Document.pdf";
for (int i = 0; i <4000; i++)
{
ImageSource img = path.GetIconFromFolder();
}
有人知道这个的明显原因吗?
答案 0 :(得分:6)
你的HANDLE
已经不多了。 Windows具有有限数量的句柄,当您获得一个句柄(在这种情况下是图标的句柄)时,您应该在不再使用它之后释放它。如果不这样做,Windows将耗尽免费句柄。
如果SHGetFileInfo在psfi指向的SHFILEINFO结构的hIcon成员中返回一个图标句柄,你负责在不再需要它时使用DestroyIcon释放它。
因此,您需要PInvoke DestroyIcon
并在功能结束时将shinfo.hIcon
传递给它。
使用FromHandle
创建的图标的处理不会破坏原始句柄:
使用此方法时,必须使用Win32 API中的DestroyIcon方法处置原始图标,以确保释放资源。