C# 使用SHFILEINFO获取文件图标

C# 使用SHFILEINFO获取文件图标,c#,shell,icons,C#,Shell,Icons,我一直在寻找一个c#库,它可以获取给定路径的图标,并且有很多大小,最后当我得到我需要的类时,它出现了一个问题: 此方法获取给定路径的图标: public static BitmapSource GetIcon(string FileName, bool small, bool checkDisk, bool addOverlay) { SHFILEINFO shinfo = new SHFILEINFO(); uint SHGFI_USEFILEATTR

我一直在寻找一个c#库,它可以获取给定路径的图标,并且有很多大小,最后当我得到我需要的类时,它出现了一个问题:

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

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)

在WPF_REMOTE.exe中发生类型为“System.IO.FileNotFoundException”的异常,但未在用户代码中处理该异常

其他信息:找不到指定的文件。

为什么会发生这种情况? 更新:我发现发生这种情况是因为有一个包含unicode字符的路径,我需要使用SHFILEINFOW,但我仍然不知道如何将
SHFILEINFO
更改为
SHFILEINFOW

关于行
CloseHandle(shinfo.hIcon)的另一个问题始终给出一个异常:

WPF_REMOTE.exe中发生了“System.Runtime.InteropServices.SEHException”类型的异常,但未在用户代码中处理

其他信息:外部组件引发了异常。

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


另外,如果您有任何改进,我可以在本课程中使用,请提前告诉我,谢谢。

编辑一些代码后,我得到了它,您可以很容易地从这个库中获得图标,在我的情况下,我需要的图标是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;
    }

}
你可以得到四种不同尺寸的图标