Click here to Skip to main content
11,703,617 members (64,894 online)
Click here to Skip to main content

Extract icons from EXE or DLL files

, 10 Nov 2014 BSD 96.1K 6.9K 128
Rate this:
Please Sign up or sign in to vote.
Extract all the variations of an icon, including the ones ExtractIconEx() can't extract.

IconExtractor Sample App

(Sample Application running on Windows Technical Preview build 9860)

Introduction

Here I will introduce a .NET class library for extracting an icon from an EXE or DLL file. Though it's common to use ExtractIconEx() Win32 API function for this purpose, it can extract only a few variations of an icon. Look at the screenshot above. This library enables us to extract all the variations and split it into separate objects.

I posted the first version of this article around six years ago. Honestly, I have been a bit ashamed of it lately. It discussed almost nothing, the code was dirty, buggy, inefficient, blah blah blah... So I rewrote the overall article, sample code and library itself. The significant updates are:

  • Can load a 64-bit DLL/EXE from 32-bit process, and vice versa
  • Recognizes huge icons used in Windows Technical Preview (i.e. 768 x 768)
  • More memory efficient
  • No longer implements IDisposable
  • Some utility methods moved to IconUtil class

Using the library

This library consists of two classes: IconExtractor and IconUtil. IconExtractor is the main class of this library. It is associated to a file and enables us to extract icons from it. IconUtil is a misc utility class.

This is a quite small and simple library. So the short example below covers all the methods and properties.

using System;
using System.Drawing;
using TsudaKageyu;

// -----------------------------------------------------------------------------
// Usage of IconExtractor class:

// Construct an IconExtractor object with a file.

IconExtractor ie = new IconExtractor(@"D:\sample.exe");

// Get the full name of the associated file.

string fileName = ie.FileName;

// Get the count of icons in the associated file.

int iconCount = ie.Count;

// Extract icons individually.

Icon icon0 = ie.GetIcon(0);
Icon icon1 = ie.GetIcon(1);

// Extract all the icons in one go.

Icon[] allIcons = ie.GetAllIcons();

// -----------------------------------------------------------------------------
// Usage of IconUtil class:

// Split the variations of icon0 into separate icon objects.

Icon[] splitIcons = IconUtil.SplitIcon(icon0);

// Convert an icon into bitmap. Unlike Icon.ToBitmap() it preserves the transparency.

Bitmap bitmap = IconUtil.ToBitmap(splitIcon[1]);

// Get the bit count of an icon.

int bitDepth = IconUtil.GetBitCount(splitIcon[2]);

How it works

The basic strategy used in this library is: Manipulate an .ico file in memory. As it's difficult and risky to manipulate the internal data of Icon object directly (It's possible, but a kind of black magic). However, once coverted into an .ico file like following, its structure is the common knowledge among Windows developers.

// Construct an Icon object.

Icon icon0 = new Icon(...);

// Convert an Icon object to an .ico file in memory.

MemoryStream ms = new MemoryStream();
icon0.Save(ms);

// Manipulate the in-memory file.

// Convert the in-memory file into an Icon object.

Icon icon1 = new Icon(ms);

Actually, an Icon object stores its own file image internally. So this library directly access to the internal buffer instead of saving to MemoryStream.

.ico file structure

An .ico file is an archive of some pictures. It consists of the count of pictures, brief information on each picture, and the actual pictures. It has a quite straightforward format, so it's easy to manipulate it. The image below roughly illustrates the structre of an .ico file and how to split and merge it.

Split and merge an .ico file

If you need more detailed information, refer to the official document of Microsoft.

Gathering the icon resource and build an .ico file

Creating an icon from resource is a similar process to merging icons.

The icons and other materials are embedded in the executable file in binary form. Those pieces cannot be loaded directly with .NET classes, because they are different from the managed resources that .NET Framework can handle. They should be loaded with Win32 API functions such as FindResource(), LoadResource() etc.

private byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
{
    // Load the binary data from the specified resource.

    IntPtr hResInfo = NativeMethods.FindResource(hModule, name, type);
    if (hResInfo == IntPtr.Zero)
        throw new Win32Exception();

    IntPtr hResData = NativeMethods.LoadResource(hModule, hResInfo);
    if (hResData == IntPtr.Zero)
        throw new Win32Exception();

    IntPtr pResData = NativeMethods.LockResource(hResData);
    if (pResData == IntPtr.Zero)
        throw new Win32Exception();

    uint size = NativeMethods.SizeofResource(hModule, hResInfo);
    if (size == 0)
        throw new Win32Exception();

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

    return buf;
}

It looks compilcated, but has some historical reasons date back to 16-bit Windows. A well-known Microsoft blogger Raymond Chen discussed it here and here.

The binary data stored in the resource is in similar form to an .ico file, so we can easily convert the data to an .ico file. 

History

  • 11 Nov, 2014: Overall revision
  • 10 Jun, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

Tsuda Kageyu
Software Developer
Japan Japan
In 1985, I got my first computer Casio MX-10, the cheapest one of MSX home computers. Then I began programming in BASIC and assembly language, and have experienced over ten languages from that time on.
Now, my primary languages are C++ and C#. Working for a small company in my home town in a rural area of Japan.


You may also be interested in...

Comments and Discussions

 
Questionadded a Save button Pin
Roland from The Netherlands4-Aug-15 6:07
memberRoland from The Netherlands4-Aug-15 6:07 
Questionusing TsudaKageyu; Pin
mick sinc1-Aug-15 11:01
membermick sinc1-Aug-15 11:01 
AnswerRe: using TsudaKageyu; Pin
Roland from The Netherlands4-Aug-15 6:00
memberRoland from The Netherlands4-Aug-15 6:00 
BugCan't extract icons Pin
Gianluca Negrelli22-Jul-15 21:36
memberGianluca Negrelli22-Jul-15 21:36 
GeneralRe: Can't extract icons Pin
Tsuda Kageyu22-Jul-15 21:45
memberTsuda Kageyu22-Jul-15 21:45 
QuestionFolders and other icons in good quality, all sizes in one file. Pin
Member 115623954-Apr-15 0:10
memberMember 115623954-Apr-15 0:10 
QuestionWhy the streams are disposed .. Pin
Member 687016823-Mar-15 8:22
memberMember 687016823-Mar-15 8:22 
AnswerRe: Why the streams are disposed .. Pin
Tsuda Kageyu23-Mar-15 8:29
memberTsuda Kageyu23-Mar-15 8:29 
Questionありがとう Pin
wmjordan29-Oct-14 17:16
memberwmjordan29-Oct-14 17:16 
SuggestionFor WPF users, here is BitmapImage code to add to this project Pin
Anarchi29-Oct-13 0:32
memberAnarchi29-Oct-13 0:32 
BugAbruptly exits after loading some DLL files Pin
Dwedit_17-Dec-12 15:38
memberDwedit_17-Dec-12 15:38 
QuestionJust a note Pin
Aleksei Karimov30-May-12 18:06
memberAleksei Karimov30-May-12 18:06 
GeneralGood Pin
Carlos Ernesto Fuentes Rasique17-Dec-11 4:18
memberCarlos Ernesto Fuentes Rasique17-Dec-11 4:18 
GeneralMy vote of 5 Pin
joehoper20-Nov-11 3:48
memberjoehoper20-Nov-11 3:48 
AnswerThanks Pin
pahancs13-Oct-11 16:06
memberpahancs13-Oct-11 16:06 
QuestionIconExtractor Program Pin
Scott Caryer26-Jul-11 9:24
memberScott Caryer26-Jul-11 9:24 
AnswerRe: IconExtractor Program Pin
AbbydonKrafts31-Jul-11 9:40
memberAbbydonKrafts31-Jul-11 9:40 
QuestionWould not work with Windows 7 64 bit OS machine Pin
elderdo6-Jul-11 13:02
memberelderdo6-Jul-11 13:02 
AnswerRe: Would not work with Windows 7 64 bit OS machine Pin
AbbydonKrafts31-Jul-11 9:35
memberAbbydonKrafts31-Jul-11 9:35 
GeneralRe: Would not work with Windows 7 64 bit OS machine Pin
solopaul_201219-Dec-12 4:40
membersolopaul_201219-Dec-12 4:40 
AnswerRe: Would not work with Windows 7 64 bit OS machine Pin
Tsuda Kageyu19-Dec-12 4:48
memberTsuda Kageyu19-Dec-12 4:48 
GeneralUnable to Convert 256x256 Icons from Microsoft Applications to Bitmap Pin
johndotthinix1-Dec-10 4:34
memberjohndotthinix1-Dec-10 4:34 
QuestionHow to determine if DLL or EXE has Icons? Pin
f r i s c h11-Feb-10 22:10
memberf r i s c h11-Feb-10 22:10 
GeneralThanx! Pin
Muammar©12-Sep-08 22:09
memberMuammar©12-Sep-08 22:09 
GeneralGood work but this way has already been taken... Pin
Guillaume Leparmentier11-Jun-08 2:45
memberGuillaume Leparmentier11-Jun-08 2:45 
GeneralRe: Good work but this way has already been taken... Pin
Tsuda Kageyu11-Jun-08 10:43
memberTsuda Kageyu11-Jun-08 10:43 
GeneralNice Pin
Saurabh.Garg10-Jun-08 5:18
memberSaurabh.Garg10-Jun-08 5:18 
GeneralRe: Nice Pin
Tsuda Kageyu10-Jun-08 10:45
memberTsuda Kageyu10-Jun-08 10:45 
GeneralNice Pin
holy_spirit10-Jun-08 4:12
memberholy_spirit10-Jun-08 4:12 
AnswerRe: Nice Pin
Tsuda Kageyu10-Jun-08 10:42
memberTsuda Kageyu10-Jun-08 10:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150819.1 | Last Updated 10 Nov 2014
Article Copyright 2008 by Tsuda Kageyu
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid