从文件夹system32获取所有图标。 System.ArgumentException

时间:2016-09-14 16:18:02

标签: c# icons intptr

我试图在文件夹system32中获取文件和文件夹的图标,但在不同的文件上获取"System.ArgumentException" in System.Drawing.dll

我创建了一个类:

[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
    public IntPtr hIcon;
    public IntPtr iIcon;
    public uint dwAttributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string szDisplayName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
}

class Win32
{
    public const uint SHGFI_ICON = 0x100;
    //public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
    public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

    [DllImport("shell32.dll")]
    public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
    [DllImport("gdi32.dll", SetLastError = true)]
    public static extern bool DeleteObject(IntPtr hObject);
}

获取图标:

 private Icon GetIcon(string filePatch)
 {
     Icon icon;
     SHFILEINFO shinfo = new SHFILEINFO();

     IntPtr hIconSmall = Win32.SHGetFileInfo(filePatch, 0, ref shinfo, /*(uint)Marshal.SizeOf(shinfo)*/ 80, Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);

     if (hIconSmall == IntPtr.Zero)
     {
         icon = iconUnknown;
     }
     else
     {
         icon = Icon.FromHandle(shinfo.hIcon);
         //"System.ArgumentException" in System.Drawing.dll
     }

     Win32.DeleteObject(shinfo.hIcon);

     return (icon);
 }

我知道我需要DeleteObject,但这似乎不会发生。我做错了什么?

PS:在属性项目中,我检查Any CPU

1 个答案:

答案 0 :(得分:0)

// I got a form with a virtual listview and a icon list
// there may be some mistakes I had to edit it together

public class DirContent // directory content like one file or one folder
{
    public string Name;
    public string Path;
    public string Modyfied;
    public string Extention;
    public string Size;
}

public class DirectoryContent //this contains a list with mulyble files and folders and the previous folder and selected folder
{
    public List<DirContent> dirContent = new List<DirContent>();
    public string previousDirectory;
    public string selectedDirectory;
}

public partial class Form1 : Form
{
    static Dictionary<string, int> IconDictornary = new Dictionary<string, int>(); //this is a Dictionary to keep track of the loaded files;
    static DirContent directoryContent = // file to load the icon for 

    public Form1()
    {
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Icon icon = Icon.ExtractAssociatedIcon(@"path/to/file/file.png");
        icons.Images.Add("empty", icon); // add empty file icon to imageList of form; (index 1) (index 0 = folder icon) i set that in imagelist propperites
    }

    public void getFileIcon() // I had a list view and had to cut out some things to show only the usefull stuf
    {
        // I had a virtual list view it much better for rendering. The system32 folder contains allot of files. so this is a handy thing 
        int index;
        if (itemIndex == 0) // i checked if the index of te listview item that has to render == 0;
        {
            ListViewItem parrentItem = new ListViewItem("", 0);
            parrentItem.SubItems.Add("..");
            parrentItem.SubItems.Add("");
            parrentItem.SubItems.Add("");
            listview[itemIndex].Item = parrentItem;

            // set on index 0 of list view a .. for previous folder
        }
        else
        {
            if (IconDictornary.ContainsKey(directoryContent[ItemIndex].Extention)) // If the icon already loaded in to  IconDictornary get the key that wil be presented by the index of the icon in the icon list;
            {
                index = IconDictornary[directoryContent[ItemIndex].Extention];
            }
            else
            {
                index = GetIconIndexFromIcon(directoryContent[ItemIndex].Extention); // get File/folder icon
            }

            ListViewItem lvi = new ListViewItem("", index); // image index of icon in icon list 
            lvi.SubItems.Add(directoryContent[ItemIndex].Name);
            lvi.SubItems.Add(directoryContent[ItemIndex].Modyfied);
            lvi.SubItems.Add(directoryContent[ItemIndex].Size);
            listview[itemIndex].Item = lvi;

            // set details for sub items and show it to list view
        }
    }

    private int GetIconIndexGetIcon(string extention)
    {
        Icon icon;
        int index = 0;
        try
        {
            if (extention == ".folder") // i check if the file extention  = .folder if yes index = 0; iconlist[0] == folder. as I sayd above
            {
                index = 0;
            }
            else
            {
                icon = Icons.IconFromExtension(extention, Icons.SystemIconSize.Large); // get icon by extention
                icons.Images.Add(extention, icon); // add to icon list with key, icon 
                index = icons.Images.IndexOfKey(extention);
                IconDictornary.Add(extention, index); // set loaded file to IconDictornary by extention and index from the icon list
            }
        }
        catch
        {
            index = 1;
        }
        return index; // return index where to find icon
    }

}

我用来获取图标的方法:

    public static Icon IconFromExtension(string extension,
                                            SystemIconSize size)     
    {
        try
        {
            // Add the '.' to the extension if needed
            if (extension[0] != '.') extension = '.' + extension;

            //opens the registry for the wanted key.
            RegistryKey Root = Registry.ClassesRoot;
            RegistryKey ExtensionKey = Root.OpenSubKey(extension);
            ExtensionKey.GetValueNames();
            RegistryKey ApplicationKey =
                Root.OpenSubKey(ExtensionKey.GetValue("").ToString());

            //gets the name of the file that have the icon.
            string IconLocation =
                ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString();
            string[] IconPath = IconLocation.Split(',');

            if (IconPath[1] == null) IconPath[1] = "0";
            IntPtr[] Large = new IntPtr[1], Small = new IntPtr[1];

            //extracts the icon from the file.
            ExtractIconEx(IconPath[0],
                Convert.ToInt16(IconPath[1]), Large, Small, 1);
            return size == SystemIconSize.Large ?
                Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]);
        }
        catch (Exception ex)
        {
            return null;
        }
    }

需要包括Dll:

     struct SHFILEINFO
    {
        public IntPtr hIcon;

        public IntPtr iIcon;

        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };

    [Flags]
    enum FileInfoFlags : int
    {
        SHGFI_ICON = 0x000000100,
        SHGFI_USEFILEATTRIBUTES = 0x000000010
    }

    [DllImport("Shell32", CharSet = CharSet.Auto)]
    extern static int ExtractIconEx(
        [MarshalAs(UnmanagedType.LPTStr)]
        string lpszFile,
        int nIconIndex,
        IntPtr[] phIconLarge,
        IntPtr[] phIconSmall,
        int nIcons);

    [DllImport("Shell32", CharSet = CharSet.Auto)]
    extern static IntPtr SHGetFileInfo(
        string pszPath,
        int dwFileAttributes,
        out SHFILEINFO psfi,
        int cbFileInfo,
        FileInfoFlags uFlags);