3

I have a path of some program (for example explorer), how can I get program icon, convert it to png/jpeg and then display in PictureBox?

I have something like this:

string filePath = "C:\\myfile.exe";
Icon TheIcon = IconFromFilePath(filePath);
if (TheIcon != null) {

 // But then I don't know what to do...

}

public Icon IconFromFilePath(string filePath){
 Icon programicon = null;
 try {
  programicon = Icon.ExtractAssociatedIcon(filePath);
 }
 catch { } 
 return programicon;
}

I found something similar here. Here is the icon. How I can create 32-bit icon?

256 colors

Community
  • 1
  • 1

2 Answers2

10

The code is surprisingly simple if you know where to look. Start with the Icon class, since that's fundamentally what you're after here.

If you browse its methods, you'll come across a very interesting looking ExtractAssociatedIcon. That accepts a single string parameter that specifies the path to a file containing an icon, such as an executable file.

So that gives you an Icon object, now you just need to display it in a PictureBox. You don't have to convert it to a PNG or JPEG, a bitmap works fine. And there's a built-in member function for that: ToBitmap.

Assigning the new bitmap to the PictureBox.Image property is all you need to do to display it.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    OK. It worked... But now I have this problem: icon is in 256 color mode, how can I create 32-bit icon? –  Jul 24 '13 at 10:19
  • Same problem. Icon.ExtractAssociatedIcon only read a single icon 'view' (I don't know how to name distinct image embedded into a single icon). I really need to get complete icon stream. – MuiBienCarlota Jul 04 '16 at 11:21
  • You cannot have distinct images embedded into a single icon. Do you mean different *sizes*, @Mui? Or possibly bit depths? ExtractAssociatedIcon is going to extract the icon with the size and bit depth used by the shell, which is generally what you want. If you need a different format of icon, then you will need to jump through some extra hoops, either P/Invoking other functions from the Windows API or manually spelunking through the resource file. The Icon class is COM-based and doesn't support 256x256 pixel icons. Ask a new question about it if you need more help. – Cody Gray - on strike Jul 04 '16 at 11:34
  • @Cody Gray Yes, by view or image, I mean 'visual representation' of a single icon (ie size, color depth and bits). I need, if possible, to extract from an exe file, the exact .ico content used to create exe file. – MuiBienCarlota Jul 04 '16 at 11:42
  • I don't know what you mean by "the exact .ico content used to create exe file." You don't create EXE files with ICO content. Anyway, I wrote [another answer](http://stackoverflow.com/a/37419253/366904) recently about extracting non-default-sized icons from files. Intended for use with EXE files. If you have a standalone ICO file, or an ICO file embedded in your own EXE as a resource, you can simply call the `LoadImage` function, passing the desired width and height values. No way to control which bit depth you get; the OS gives you the correct one for your display characteristics. – Cody Gray - on strike Jul 04 '16 at 11:51
  • If you need to get a certain bit depth that doesn't match your screen (I don't know why you would need to do this, though), then you will have to load the resource file manually and parse the icon out. None of this is wrapped by the .NET Framework, so you'll need to write P/Invoke code. @mui – Cody Gray - on strike Jul 04 '16 at 11:52
  • @Cody Gray You're right, I've summarized my needs in its own question: http://stackoverflow.com/questions/38185140/how-to-extract-from-exe-file-the-same-ico-file-as-the-one-used-to-create-this-e – MuiBienCarlota Jul 04 '16 at 12:48
0

This question might be old but here's my answer. Here's a full code snippet I used in extracting full 256 x 256 icons from any exe file.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace IconUtils
{
    internal static class ExtractIcon
    {
       [UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
       [SuppressUnmanagedCodeSecurity]
        internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern IntPtr LockResource(IntPtr hResData);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       [SuppressUnmanagedCodeSecurity]
       public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);


       private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
       private readonly static IntPtr RT_ICON = (IntPtr)3;
       private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;

       public static Icon ExtractIconFromExecutable(string path)
       {
           IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
           var tmpData = new List<byte[]>();

           ENUMRESNAMEPROC callback = (h, t, name, l) =>
           {
               var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);

               // Calculate the size of an entire .icon file.

               int count = BitConverter.ToUInt16(dir, 4);  // GRPICONDIR.idCount
               int len = 6 + 16 * count;                   // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
               for (int i = 0; i < count; ++i)
                   len += BitConverter.ToInt32(dir, 6 + 14 * i + 8);   // GRPICONDIRENTRY.dwBytesInRes

               using (var dst = new BinaryWriter(new MemoryStream(len)))
               {
                   // Copy GRPICONDIR to ICONDIR.

                   dst.Write(dir, 0, 6);

                   int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count

                   for (int i = 0; i < count; ++i)
                   {
                       // Load the picture.

                       ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12);    // GRPICONDIRENTRY.nID
                       var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);

                       // Copy GRPICONDIRENTRY to ICONDIRENTRY.

                       dst.Seek(6 + 16 * i, 0);

                       dst.Write(dir, 6 + 14 * i, 8);  // First 8bytes are identical.
                       dst.Write(pic.Length);          // ICONDIRENTRY.dwBytesInRes
                       dst.Write(picOffset);           // ICONDIRENTRY.dwImageOffset

                       // Copy a picture.

                       dst.Seek(picOffset, 0);
                       dst.Write(pic, 0, pic.Length);

                       picOffset += pic.Length;
                   }

                   tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
               }
               return true;
           };
           EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
           byte[][] iconData = tmpData.ToArray();
           using (var ms = new MemoryStream(iconData[0]))
           {
               return new Icon(ms);
           }
       }
       private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
       {
           // Load the binary data from the specified resource.

           IntPtr hResInfo = FindResource(hModule, name, type);

           IntPtr hResData = LoadResource(hModule, hResInfo);

           IntPtr pResData = LockResource(hResData);

           uint size = SizeofResource(hModule, hResInfo);

           byte[] buf = new byte[size];
           Marshal.Copy(pResData, buf, 0, buf.Length);

           return buf;
       }
   }
}

Usage:

Icon ExeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(@"C:\Windows\explorer.exe");

Source: https://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files

Alizer
  • 61
  • 1
  • 5