Search code examples
c#.netwinapiiconsregistry

How to extract icons from an executable?


I'm working on a personal project in which I'd like to give the opportunity to the user to browse and work with the registry (the HKCU key) just like he would do with regedit.exe.

Everything works fine, but I'd like now to somehow extract the icons associated with the registry values.
Does anyone has an idea on how I can achieve something like this?

Example of Icons I'd like to get:

Example of Icons I'd like to get


Solution

  • You can use ExtractIconEx() to extract those icons from regedit.exe.

    Note that regedit.exe can be found in both Windows and Windows\System32 directories. Here, I assume it's under Windows.

    Win API declarations:

      [DllImport("shell32.dll", CharSet = CharSet.Auto)]
      public static extern uint ExtractIconEx(string lpszFile, int nIconIndex, [Out] IntPtr[] phiconLarge, [Out] IntPtr[] phiconSmall, [In] uint nIcons);
    
      [DllImport("user32.dll")]
      public static extern int DestroyIcon(IntPtr hIcon);
    

    ExtractIconEx() is first called with null parameters, to get the number of icons the file contains.
    With this information, we retrieve the Small and Large Icons handles in 2 arrays and create a GDI+ Icon from those handles using Icon.FromHandle().

    string icnSource = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "regedit.exe");
    
    uint icnNumber = ExtractIconEx(icnSource, -1, null, null, 1);
    
    if (icnNumber > 0)
    {
        IntPtr[] phiconLarge = new IntPtr[icnNumber];
        IntPtr[] phiconSmall = new IntPtr[icnNumber];
        ExtractIconEx(icnSource, 0, phiconLarge, phiconSmall, icnNumber);
    
        Icon[] iconsmall = new Icon[icnNumber];
        Icon[] iconlarge = new Icon[icnNumber];
    
        for (int x = 0; x < icnNumber; x++)
        {
            if (phiconLarge != null)
            {
                iconlarge[x] = (Icon)Icon.FromHandle(phiconLarge[x]).Clone();
                DestroyIcon(phiconLarge[x]);
            }
            if (phiconSmall != null)
            {
                iconsmall[x] = (Icon)Icon.FromHandle(phiconSmall[x]).Clone();
                DestroyIcon(phiconSmall[x]);
            }
        }
    }
    

    You can transform an Icon into a GDI+ Bitmap, if necessary, using Icon.ToBitmap().

    These, number 3 and 4, are the Icons you are looking for:

    pictureBox1.Image = iconsmall[3].ToBitmap();
    pictureBox2.Image = iconsmall[4].ToBitmap();