使用SHFILEINFO获取文件图标

我一直在搜索ac#library,它获取了许多大小的给定路径的图标,最后当我得到我需要的类时,它有一个问题:

此方法获取给定路径的图标:

public static BitmapSource GetIcon(string FileName, bool small, bool checkDisk, bool addOverlay) { SHFILEINFO shinfo = new SHFILEINFO(); uint SHGFI_USEFILEATTRIBUTES = 0x000000010; uint SHGFI_LINKOVERLAY = 0x000008000; uint flags; if (small) { flags = SHGFI_ICON | SHGFI_SMALLICON; } else { flags = SHGFI_ICON | SHGFI_LARGEICON; } if (!checkDisk) flags |= SHGFI_USEFILEATTRIBUTES; if (addOverlay) flags |= SHGFI_LINKOVERLAY; var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags); if (res == 0) { throw (new System.IO.FileNotFoundException()); } var ico = System.Drawing.Icon.FromHandle(shinfo.hIcon); //**Here** var bs = BitmapFromIcon(ico); ico.Dispose(); bs.Freeze(); DestroyIcon(shinfo.hIcon); // CloseHandle(shinfo.hIcon); it always give exception return bs; } public static extern Boolean CloseHandle(IntPtr handle); 

此问题中的上一个代码正如它所设想的那样工作 ,但是在成功获取目录中的文件路径图标之后,它在此行上给出了一个例外:
var ico = System.Drawing.Icon.FromHandle(shinfo.hIcon);

An exception of type 'System.IO.FileNotFoundException' occurred in WPF_REMOTE.exe but was not handled in user code

Additional information: Unable to find the specified file.

那么为什么会这样呢? 更新:我发现它发生的原因是因为有一个包含unicode字符的路径而我需要使用SHFILEINFOW,仍然无法SHFILEINFO如何将SHFILEINFO更改为SHFILEINFOW

关于CloseHandle(shinfo.hIcon);行的另一个问题CloseHandle(shinfo.hIcon); 总是给出一个例外:

An exception of type 'System.Runtime.InteropServices.SEHException' occurred in WPF_REMOTE.exe but was not handled in user code

Additional information: External component has thrown an exception.

我想知道它为什么不起作用! 如果方法在没有它的情况下已经工作,我为什么要使用它。

如果你有任何改进我可以在这堂课中使用告诉我,在此先感谢。

编辑完一些代码后,我就可以从这个库中轻松获取图标,在我的情况下,我需要将图标作为byte []

 public class IconHelper { // Constants that we need in the function call private const int SHGFI_ICON = 0x100; private const int SHGFI_SMALLICON = 0x1; private const int SHGFI_LARGEICON = 0x0; private const int SHIL_JUMBO = 0x4; private const int SHIL_EXTRALARGE = 0x2; // This structure will contain information about the file public struct SHFILEINFO { // Handle to the icon representing the file public IntPtr hIcon; // Index of the icon within the image list public int iIcon; // Various attributes of the file public uint dwAttributes; // Path to the file [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szDisplayName; // File type [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; [System.Runtime.InteropServices.DllImport("Kernel32.dll")] public static extern Boolean CloseHandle(IntPtr handle); private struct IMAGELISTDRAWPARAMS { public int cbSize; public IntPtr himl; public int i; public IntPtr hdcDst; public int x; public int y; public int cx; public int cy; public int xBitmap; // x offest from the upperleft of bitmap public int yBitmap; // y offset from the upperleft of bitmap public int rgbBk; public int rgbFg; public int fStyle; public int dwRop; public int fState; public int Frame; public int crEffect; } [StructLayout(LayoutKind.Sequential)] private struct IMAGEINFO { public IntPtr hbmImage; public IntPtr hbmMask; public int Unused1; public int Unused2; public Rect rcImage; } [DllImport("shell32.dll", EntryPoint = "#727")] private extern static int SHGetImageList( int iImageList, ref Guid riid, out IImageList ppv ); // The signature of SHGetFileInfo (located in Shell32.dll) [DllImport("Shell32.dll", CharSet = CharSet.Unicode)] public static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags); [DllImport("Shell32.dll", CharSet = CharSet.Unicode)] public static extern int SHGetFileInfo(IntPtr pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags); [DllImport("shell32.dll", SetLastError = true)] static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, Int32 nFolder, ref IntPtr ppidl); [DllImport("user32")] public static extern int DestroyIcon(IntPtr hIcon); public struct pair { public System.Drawing.Icon icon { get; set; } public IntPtr iconHandleToDestroy { set; get; } } private static byte[] ByteFromIcon(System.Drawing.Icon ic) { var icon = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(ic.Handle, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); icon.Freeze(); byte[] data; PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(icon)); using (MemoryStream ms = new MemoryStream()) { encoder.Save(ms); data = ms.ToArray(); } return data; } private static byte[] GetSmallIcon(string FileName, IconSize iconSize) { SHFILEINFO shinfo = new SHFILEINFO(); uint flags; if (iconSize == IconSize.Small) { flags = SHGFI_ICON | SHGFI_SMALLICON; } else { flags = SHGFI_ICON | SHGFI_LARGEICON; } var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags); if (res == 0) { throw (new System.IO.FileNotFoundException()); } var ico = (System.Drawing.Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon); var bs = ByteFromIcon(ico); ico.Dispose(); DestroyIcon(shinfo.hIcon); return bs; } private static byte[] GetLargeIcon(string FileName) { SHFILEINFO shinfo = new SHFILEINFO(); uint SHGFI_SYSICONINDEX = 0x4000; int FILE_ATTRIBUTE_NORMAL = 0x80; uint flags; flags = SHGFI_SYSICONINDEX; var res = SHGetFileInfo(FileName, FILE_ATTRIBUTE_NORMAL, ref shinfo, Marshal.SizeOf(shinfo), flags); if (res == 0) { throw (new System.IO.FileNotFoundException()); } var iconIndex = shinfo.iIcon; Guid iidImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950"); IImageList iml; int size = SHIL_EXTRALARGE; var hres = SHGetImageList(size, ref iidImageList, out iml); // writes iml IntPtr hIcon = IntPtr.Zero; int ILD_TRANSPARENT = 1; hres = iml.GetIcon(iconIndex, ILD_TRANSPARENT, ref hIcon); var ico = System.Drawing.Icon.FromHandle(hIcon); var bs = ByteFromIcon(ico); ico.Dispose(); DestroyIcon(hIcon); return bs; } } 

并且您可以为图标获得四种不同的尺寸