Icon Browser: An Exercise in Resource Management

提取EXE图标 void CTest::OnBnClickedButton() { LPCTSTR lpszExePath=L"C:\\Windows\\System32\\notepad.exe"; LPCTSTR lpszExePath1 = L"C:\\Users\\Administrator\\AppData\\Roaming\\360se6\\Application\\360se.exe"; H 阅读详情

Icon Browser: An Exercise in Resource Management

By Kenny Kerr, November 2001

 

Summary Info

Prerequisites

This article assumes you’re familiar with C++, C#, and .NET programming.

Article Summary

The System.Runtime.InteropServices namespace contains many useful classes, structures and attributes that you can use to access your legacy libraries and resources. The .NET Framework as a whole also provides many services for migrating existing code and resources to managed code. This article explains how to use these services to extract resources from Win32 resource files as well as how to write icon resources to .ICO files. It also covers many of the issues surrounding resource management and interoperating with unmanaged code, memory and binary formats.

Resources

.NET Framework System.Runtime.InteropServices Namespace
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemRuntimeInteropServices.asp

Platform SDK Documentation for Resource Functions
http://msdn.microsoft.com/library/en-us/winui/resource_0jsj.asp

Icons in Win32
http://msdn.microsoft.com/library/en-us/dnwui/html/msdn_icons.asp

Downloads

Kerr.IconBrowser.exe - The executable for the Icon Browser application. You need the .NET Framework SDK Release Candidate installed to run it.

Source Code - The full source code for the application. Ideally you would open this in Visual Studio .NET Release Candidate, but you can also build this using just the SDK (with a bit more effort).

 

Introduction

Every so often I find myself needing to extract an icon from an executable or dynamic-link library (DLL). And every time I end up bending over backwards to get this done, especially if the library contains hundreds of icons and I have to sift through all of them until I find the one I want. So I decided to write a little program to make the process of extracting an icon from a library much easier. Well it started out simple. I wrote the Icon Browser application in C# using the .NET Framework and in about 45 minutes I had a really cool icon viewer. Then I attempted to implement the Export feature that would allow the user to choose any icon in the library and save it to an external .ICO file. I hit a brick wall. It turns out there’s no simple way to save an icon to a file.

In this article I present the Icon Browser application. It is a small desktop application that allows you to browse through the icons embedded in executables and DLLs. It also allows you to save any of the icons to a .ICO file. I will use this application as a vehicle for exploring programming tasks such as reading and writing unmanaged resources and other issues related to porting or coexisting with legacy code and binaries. In addition, I’ll look at taking C++ classes employing traditional deterministic finalization and show you how to implement them as C# classes, ensuring that they behave well in the .NET environment.

 

Icon Browser

Before we get into the programming details let me quickly introduce the Icon Browser and show you how you can use it. Even if you’re not too interested in resource management and interoperating with unmanaged code from .NET, you might find this application useful. Icon Browser is very easy to use (see Figure 1). You can type a file name in the edit box and click the Go button and Icon Browser will search the given file and display any icons it finds in the list view. If you’re not sure about the name or location of the file you can click the Browse button and search for a file using the familiar ‘Choose a File’ dialog box. Once the icons have been loaded into Icon Browser you can choose any of the icons and click the Export Icon button to save the icon to a .ICO file. You will be presented with a ‘Save Icon As’ dialog box so that you can indicate where to save the new .ICO file. I’ve also added a handy context menu to the list view so that you can just right click on an icon and select the Export Icon command.

Figure 1 - The Icon Browser Application

If you are following along with me on your own computer you will notice that there is a default file name in the Save Icon As dialog box and it’s probably a number. You might be wondering what this number is. The name or number is what is known as the resource name for the icon in the library. It’s just a unique way to identify a resource in a library. The resource name is also used as the title for each of the icons that are displayed in Icon Browser (see Figure 1).

And that’s the Icon Browser application, simple but effective! The application as well as its source code is available with the download for this article.

 

What Are Icons Anyway?

Most people think of icons as the little images that represent documents and other files in the Windows shell. Technically, an icon is a group of icon images. An icon image resembles that of a device-independent bitmap. So an icon can be represented by a number of different images tailored for different display configurations. In fact, when designing icons for Windows XP you are encouraged to include 9 different images. Figure 2 shows the images for Microsoft Notepad in GIF Movie Gear, which is a tool you can use to assemble icon images and save to a .ICO file.

Figure 2 - Notepad Icon Images

When using an icon you will typically only deal with a handle to the icon and not the actual icon resource. In C or C++ you will use the HICON, which is simply an abstract handle to the icon and pass it to the various Win32 API calls. This is the traditional way that resources are managed in C. In the managed world of .NET you will use the Icon class.

 

Loading Icons, So Many Choices!

There are many different ways to load an icon. Two of the most common functions you can use are ExtractIcon and LoadIcon. ExtractIcon will return an HICON given a file name and the zero-based index of the icon in the file. This is useful if you just want to enumerate all or some of the icons in a file. LoadIcon is a bit more useful in that you can identify an icon based on its resource name or identifier. In .NET you don’t generally load icons from unmanaged executables or DLLs. Instead you will normally use the ResourceManager class to load resources from resource files as defined by the .NET Framework.

So how do I read icons from unmanaged libraries? Read on.

 

Platform Invoke

Platform Invoke, which is more commonly referred to as P/Invoke, is the bridge between the managed world of .NET and unmanaged code like the Win32 APIs. P/Invoke is part of the .NET Framework’s extensive interoperability layer. To call an unmanaged function you need to use the DllImport attribute to identify the function and the DLL that implements it. Here is the declaration for the LoadIcon API.

// Original declared in: winuser.h
// HICON LoadIcon(HINSTANCE hInstance,
//                          PCTSTR pName);

[ DllImport ( "User32.dll" , SetLastError = true , CharSet = CharSet . Auto )]
public static extern IntPtr LoadIcon ( IntPtr hInstance ,
                                                   IntPtr pName );

“User32.dll” is the single parameter to the DllImportAttribute instance constructor. It identifies the DLL implementing the unmanaged function. SetLastError and CharSet are public fields for the DllImportAttribute class.

Setting the SetLastError field to true informs the Common Language Runtime (CLR) that the unmanaged function may call the SetLastError Win32 API function. In response the CLR will cache the value returned by the GetLastError Win32 API function so that you can retrieve it later. This is to avoid race conditions, as it is possible for another function used by the CLR to call SetLastError before you get around to retrieving the error code. The .NET Framework exposes the cached error code through the GetLastWin32Error static method on the Marshal class. So it is a good idea to set this field if you suspect your unmanaged functions may set the last error code and you are interested in retrieving it.

Setting the CharSet field to CharSet.Auto indicates that the unmanaged function has a Unicode and an Ansi version. Most Win32 API functions that deal in any way with strings qualify. For example, there doesn’t actually exist a function named LoadIcon. It is actually #define’d to LoadIconW if UNICODE is defined or LoadIconA if it is not. The –W, or Unicode, versions of the functions were introduced with Windows NT as Windows NT and it successors Windows 2000 and XP deal natively with Unicode strings. Windows 9x and its successor Windows ME mostly only support the –A, or Ansi, versions. Setting CharSet to CharSet.Auto instructs the CLR to pick the right version based on the operating system that the code is running on. If you don’t explicitly set the CharSet field it defaults to CharSet.Ansi, which won’t give you the best performance on Window XP as the operating system will have to convert any strings from Ansi to Unicode before it can use them.

The next thing you’ll notice is that I’ve changed the return type and the parameter types to the IntPtr class. You will normally use IntPtr for opaque unmanaged types that can’t be represented by corresponding managed types. Although pName is a PCTSTR, which is a constant pointer to a TCHAR (in other words a string), it is more commonly used to pass an integer identifier using the MAKEINTRESOURCE marcro. For this reason pName is also declared as an IntPtr.

LoadIcon, as with many of the resource management functions, requires an instance handle. If you’re programming in C++ then this is no problem. The operating system will assign your process an instance handle when it first starts up. And if you need to get resources from another DLL or executable it’s a simple matter of calling LoadLibraryEx and passing the LOAD_LIBRARY_AS_DATAFILE flag to indicate that you just want access to the resources within the library and don’t want to execute any code it may contain. Here’s an example of using the LoadLibraryEx function to load the Windows Explorer shell executable.

HMODULE hModule = LoadLibraryEx ( _T ( “C://Windows//Explorer . exe” ),
                                                     0 , // must be zero.
                                                     LOAD_LIBRARY_AS_DATAFILE );

Although LoadLibraryEx returns a module handle, it is generally interchangeable with an instance handle so you can freely pass it to functions that expect a HINSTANCE. In fact, a HMODULE is typedef’d to be a HINSTANCE in windef.h. In the world of .NET however, you don’t deal with instance handles but rather with assemblies. An assembly, which is usually packaged as an executable or DLL, can be loaded using the Assembly.LoadFrom method as shown here.

Assembly assembly = Assembly . LoadFrom ( “C://Kerr . Resources . dll” );

The Assembly class contains a host of properties and methods for accessing the various types defined in an assembly and can be used with the classes in the System.Resources namespace to retrieve any resources.

 

Resource Management

Lets get back to the problem at hand. We want to retrieve resources from unmanaged libraries. To do this we need to declare a few of the Win32 API functions for use in .NET. I tend to put all my declarations in a single class that I call WindowsAPI. This way I can check at a glance what dependencies my project may have to ensure that they are available on any platforms that I support. You can download the WindowsAPI class along with the source code for this article. Now because resource management is so important (yes, even when using .NET), you should avoid using these functions directly as your code will end up getting quite messy as you try to free the various resources when you’re done using them. Remember that you must always write your code to be resilient to exceptions. The best way to do this is to wrap any resource management functions inside a class. If you are a C++ programmer your first pass at writing a C# class to wrap the library functions might look something like this, with error handling code omitted for brevity (see Figure 3).

Figure 3 - Unreliable Library Class

public class Library
{
     public Library ( string strFileName ,
                          ulong ulFlags )
     {
         m_hModule = WindowsAPI . LoadLibraryEx ( strFileName ,
                                                                      IntPtr . Zero ,
                                                                      UlFlags );
     }

     ~ Library ()
     {
         WindowsAPI . FreeLibrary ( m_hModule );
     }

     private IntPtr m_hModule ;
}

This is perfectly acceptable from a C++ point of view and it will even compile and work in C#. There’s only one problem. The .NET Framework uses non-deterministic finalization. What this means is that the .NET Framework’s garbage collector will call your object’s destructor (called a finalizer in .NET speak) in a non-deterministic fashion, most likely when it notices you’re low on memory. So unlike in C++ where your destructor is guaranteed to be called when execution leaves the scope in which the object was created, in .NET you cannot rely on a destructor to free your resources in such a timely fashion. Fortunately .NET defines a pattern for resource management, which if followed consistently makes resource management a breeze. The .NET Framework defines the IDisposable interface, which has a single method called Dispose. When used in conjunction with the C# using statement, it provides precise control over when your class will be disposed. So lets rewrite the Library class to make use of the IDisposable interface, again with error handling omitted for brevity (see Figure 4).

Figure 4 - Revised Library Class

public class Library : IDisposable
{
     public Library ( string strFileName ,
                         ulong ulFlags )
     {
         m_hModule = WindowsAPI . LoadLibraryEx ( strFileName ,
                                                                      IntPtr . Zero ,
                                                                      UlFlags );
     }

     ~ Library ()
     {
         Free ();
     }

     public void Dispose ()
     {
         Free ();
     }

     public void Free ()
     {
         if ( IntPtr . Zero != m_hModule )
         {
             WindowsAPI . FreeLibrary ( m_hModule );
         }

         m_hModule = IntPtr . Zero ;
     }

     private IntPtr m_hModule ;
}

You’ll notice that I still have a destructor. This is just a safeguard in case the user of my class forgets to employ the using statement. In this case the library will still get freed, eventually. My new Library class can now be used as follows.

using ( Library library = new Library ( @”C:/Windows/Explorer . exe”,
                                                    WindowsAPI . LOAD_LIBRARY_AS_DATAFILE ))
{
     // use the library
}

Before execution leaves the using scope the library will be freed. And that’s the basics of resource management in C#. Next we’ll take a look at extracting the icon resources from the library.

 

So Where Are The Icons?

Now that we know how to load an unmanaged library we need to determine whether a library contains any icons. As I mentioned before, you can use the LoadIcon function to load an icon from a library as long as you have the name or identifier for the icon resource. If you don’t know the name of a particular icon you can enumerate all the icons until you find the one you want. This is done using the EnumResourceNames function, which is declared as follows.

BOOL EnumResourceNames ( HMODULE hModule ,
                                          PCTSTR pType ,
                                          ENUMRESNAMEPROC pCallback ,
                                          LONG_PTR lParam );

The hModule parameter is a module handle, which you can get by calling LoadLibraryEx, so I can use my Library class for this. The pType parameter identifies the type of resource. Although you can define your own resource types, you will generally use one of the standard resource types. Two resource types that are of interest in this discussion are RT_GROUP_ICON and RT_ICON. An RT_GROUP_ICON resource represents an icon. It is basically just a directory of icon images. Each directory entry refers to a RT_ICON resource, which contains the actual image data (see Figure 5).

Figure 5 - RT_GROUP_ICON and RT_ICON Resource Memory Layout

So to enumerate the icons in a library you pass RT_GROUP_ICON as the type of resource to enumerate. The next parameter is the callback function, which is the traditional way of implementing an enumerator in C. You simply pass the address of a function to EnumResourceNames and it will call that function for each matching resource. Simple. Well not really. The problem is that the .NET Framework has no notion of a function pointer. Fortunately for us the .NET Framework has a thing called a delegate, which you can use to implement a callback. A delegate can refer to a static or instance method. You can’t pass EnumResourceNames a pointer to a function, but you certainly can pass it a delegate, assuming you declared the EnumResourceNames function appropriately and declared the matching delegate. Here’s how you would do that.

[ DllImport ( "Kernel32.dll" , SetLastError = true , CharSet = CharSet . Auto )]
public static extern int EnumResourceNames ( IntPtr hModule ,
                                                                 IntPtr pType ,
                                                                 EnumResNameProc callback
                                                                 IntPtr param );

public delegate bool EnumResNameProc ( IntPtr hModule ,
                                                           IntPtr pType ,
                                                           IntPtr pName ,
                                                           IntPtr param );

Since EnumResourceNames really operates on a library, I’ve added a method to my Library class for it. This saves us from having to pass it a module handle every time. And of course this is the more object-oriented way to go about it. Now to enumerate the icon resources in a library becomes very easy (see Figure 6).

Figure 6 – Using the EnumResourceNameProc Delegate

public void Main ()
{
     using ( Library library = new Library ( @”C:/Windows/Explorer . exe”
                                                         WindowsAPI . LOAD_LIBRARY_AS_DATAFILE ))
     {
         // Call the Callback method for each RT_GROUP_ICON resource that
         // is found.

         library . EnumResourceNames ( WindowsAPI . RT_GROUP_ICON ,
                                                    new WindowsAPI . EnumResNameProc ( Callback ),
                                                    IntPtr . Zero );
     }
}

public bool Callback ( IntPtr hModule ,
                               IntPtr pType ,
                               IntPtr pName ,
                               IntPtr param )
{
     // use the icon resource

     return true ; // to keep enumerating
}

At this point we can call LoadIcon to get a handle to an icon tailored for the current display configuration. This can then be passed to the Icon.FromHandle method to get an Icon object, which in turn can be displayed in various ways in a .NET application. If you recall one of my objectives for the Icon Browser application is to be able to save an icon to an .ICO file. To do this we need to dig a little deeper and get at the actual resource data.

To get the resource data we need to use the FindResource and LoadResource functions to locate and load the resource. This is different from calling LoadIcon, which generates a displayable icon based on the icon resource. Once the resource is loaded we call the LockResource function to get a pointer to the actual resource bytes. This pointer is valid until such time as the library containing the resource is freed. I’ve declared two C# structures to represent the resource data (see Figure 7).

Figure 7 – C# Strucures for RT_GROUP_ICON

[ StructLayout ( LayoutKind . Sequential , Pack = 2 )]
public struct MEMICONDIR
{
     public ushort wReserved ;
     public ushort wType ;
     public ushort wCount ;
     public MEMICONDIRENTRY arEntries ; // inline array
}

[ StructLayout ( LayoutKind . Sequential , Pack = 2 )]
public struct MEMICONDIRENTRY
{
     public byte bWidth ;
     public byte bHeight ;
     public byte bColorCount ;
     public byte bReserved ;
     public ushort wPlanes ;
     public ushort wBitCount ;
     public uint dwBytesInRes ;
     public ushort wId ;
}

You won’t find these data structures defined in the Platform SDK documentation. What complicates matters when trying to use them from C# is that MEMICONDIR is actually a variable length structure. In C++ you would declare it as follows.

struct MEMICONDIR
{
     WORD wReserved ;
     WORD wType ;
     WORD wCount ;
     MEMICONDIRENTRY arEntries [ 1 ];
};

The length of the arEntries array is defined by wCount. In other words, arEntries is an inline array as apposed to a pointer to the first element of an array. So to get to the various elements of the array you need to perform a bit of pointer arithmetic. Although this is no problem to a seasoned C or C++ developer, it poses a challenge as C# does not encourage the use of pointers. Fortunately it does not disallow it altogether. You do however need to explicitly mark code blocks as unsafe before you can make use of pointers. This can be done using the C# unsafe keyword. Please bear in mind that it is called unsafe for a reason. Misuse of pointers often leads to very buggy code. This is why even in C++ the use of pointers is discouraged and should usually be localized to C++ classes employing the ‘resource acquisition is initialization’ idiom. If you use any unsafe code in a .NET assembly the entire assembly is marked as unsafe. Figure 8 contains a simple console application that demonstrates how to load the icon resource for the Microsoft Notepad application and how to use pointer arithmetic to access the last entry in the arEntries array.

Figure 8 – Loading an Icon Resource

using System ;
using Kerr . Resources ;

class Console
{
     unsafe static void Main ()
     {
         try
         {
             // For brevity we assume Notepad is located here. To run this 
             // code yourself adjust this value accordingly.

             string strFileName = @"D:/Windows/Notepad.exe" ;

             // Load the library.

             using ( Library library = new Library ( strFileName ,
                                                                WindowsAPI . LOAD_LIBRARY_AS_DATAFILE ))
             {
                 // Notepad's icon resource identifier: 2

                 IntPtr hGroupInfo = library . FindResource ( new IntPtr ( 2 ),
                                                                            WindowsAPI . RT_GROUP_ICON );

                 // Load the icon resource.

                 IntPtr hGroupRes = library . LoadResource ( hGroupInfo );

                 // Get a pointer to the resource data.

                 WindowsAPI . MEMICONDIR * pDirectory =
                     ( WindowsAPI . MEMICONDIR *) Library . LockResource ( hGroupRes );

                 if ( 0 != pDirectory -> wCount )
                 {
                     // pEntry points to the first entry in the array.
                     WindowsAPI . MEMICONDIRENTRY * pEntry = &( pDirectory -> arEntries );

                     // Adjust the pEntry to point to the last entry.
                     pEntry += pDirectory -> wCount - 1 ;

                     // use the directory entry.
                 }
             }
         }
         catch ( Exception e )
         {
             Console . WriteLine ( "Console application failed: " + e . Message );
         }
     }
}

Now that we know how to access these structures lets take a closer look at them. Both MEMICONDIR and MEMICONDIRENTRY have the StructLayout attribute applied to them. LayoutKind.Sequential is the single parameter to the StructLayoutAttribute instance constructor. It indicates that the members of the structure must be laid out sequentially in memory so as to be memory-compatible with unmanaged code. Otherwise, the CLR is free to move the struct members around in memory for efficiency. The Pack field indicates the alignment of the members in memory. The Pack field defaults to 8, which is convenient as this is the same as what Visual C++ 6 uses. And since most unmanaged structures you might encounter were probably declared and implemented using Visual C++ 6 it is a safe default. However the icon resource uses a Pack value of 2 and that is why we need to declare it explicitly. This results in a slightly smaller memory footprint, as most of the structure members are 2 byte words or smaller. To put this in perspective you would declare the MEMICONDIR structure in C++ like this.

#pragma pack ( push )
#pragma pack ( 2 )

struct MEMICONDIR
{
     WORD wReserved ;
     WORD wType ;
     WORD wCount ;
     MEMICONDIRENTRY arEntries [ 1 ];
};

#pragma pack ( pop )

The MEMICONDIRENTRY structure contains information about an individual icon image. The wID member is of particular interest to us as it contains the resource identifier for the RT_ICON resource within the library that contains the actual image bitmap information. You can use this identifier with the FindResource and LoadResource functions to locate and load the RT_ICON resource. And then you can use the LockResource function to get at the bitmap information. Finally we’ve found the images! The RT_ICON resource data is stored in memory in a very similar way to a device-independent bitmap (DIB). So much so that we can use the BITMAPINFO structure, which defines a DIB in memory to access the RT_ICON resource data. For more information about DIB’s and the BITMAPINFO structure please consult the Platform SDK documentation. Technically the icon image uses the same format as the CF_DIB clipboard format where the DIB bits follow the BITMAPINFO header and color table. You will need to know this if you want to render the image yourself using the icon resource. For the purpose of this discussion we can ignore this fact except to remember that the BITMAPINFO is yet another variable length structure and we must treat it accordingly. One thing to keep in mind is that icons deviate slightly from the BITMAPINFOHEADER semantics in that the biHeight member is double the actual height. Figure 5 illustrates how the RT_GROUP_ICON and RT_ICON resources are laid out in memory.

Next we’ll look at how we can wrap all this resource management code in a few well-defined classes to reduce this complexity.

 

Resource Management Revisited

I have written two C# classes namely IconResource and IconImage respectively. The IconResource class takes care of loading an RT_GROUP_ICON resource from a library and populates an array of IconImage objects. Each IconImage object represents an RT_ICON resource, which is a single image for the icon resource. As a user of the IconResource class is entitled to keep a reference to an IconResource object long after the library that it originated from has been freed, we need to be careful about the memory that gets returned by calls to LockResource. Although we don’t have to worry about releasing this memory, the operating system will ensure that it is freed once its parent library is unloaded from the process, we do need to concern ourselves with any pointers to this memory that we may hold on to. The IconImage class needs to hold on to its resource data so that it can be used to write it to a .ICO file. I will talk more about this later. To satisfy this requirement the IconImage class makes a local copy of the image bits. When the IconImage object is constructed it loads the RT_ICON resource, which is just the DIB bits for the image. It then copies these image bits into a managed byte array using the Copy method on the Marshal class. So now that the IconImage class contains its own copy of the resource data, the library where the resource was originally retrieved from can be freed without affecting the IconImage class.

 

Lets See What You’ve Got!

Icons aren’t much fun if you can’t see them. So lets take a look at the Icon Browser’s MainWindow class and how it employs the classes that we’ve discussed so far to implement icon browsing. Although I am generally weary of computer generated code, the Visual Studio Forms Designer does a remarkable job of generating user interface code. It is a huge boon to productivity if handled correctly. The trick is to be conscious of the code it generates and to maintain your coding and naming standards. For example if you drag three text boxes onto a form it will name then textBox1, textBox2, and textBox3. Be sure to give them meaningful names in the context of your application as well as following any naming conventions you may be employing for your project. Further, for any non-trivial user interface component you need to emply standard design practices to ensure separation of data and presentation. This can be done using design patterns such as the Document/View pattern employed by MFC or the Model/View/Controller (MVC) pattern.

As you can see in Figure 1, the Icon Browser is a simple forms-based application. Its made up of a resizable window that contains a list view for displaying the icons as well as a tool bar of sorts exposing the functionality supported by the Icon Browser application. The code of interest is in the OkEventHandler method, which is called in response to the Click event on the OK button. This brings everything we have learnt so far together. The OkEventHandler method uses the Library class to load the user-provided file. It then calls the Library class’ EnumResourceNames method to enumerate the RT_GROUP_ICON resources. AddIconToList is the delegate called by EnumResourceNames for each icon resource that is found. It uses the IconResource class to load the resource data and adds an IconItem to the ListView to represent the icon to the user. IconItem is a simple class that derives from ListViewItem, that is used to initialize the ListViewItem text and image index.

 

Exporting Icons

There’s one more thing left to do. At the beginning of this article I mentioned that the Icon Browser would allow the user to export any icon to a .ICO file. Unfortunately for us the .ICO file format is different to the format used to store icons in resource files. Figure 9 illustrates how an icon is stored in a .ICO file. As you can see it holds somewhat of a resemblance with the memory layout of of the RT_GROUP_ICON resource. So with a little bit of translation code we can convert the one to the other. The major difference with the way the .ICO file format is written is that the icon image directory entry for each image stores an byte offset to the location of the image, whereas the RT_GROUP_ICON resource stores the resource name which you use to load the image. For the purposes of writing a .ICO file I have added a Save method to the IconResource class. This method takes a single string parameter that indicates the file to write the icon data to. It uses the BinaryWriter class to write the .ICO file header information. It then delegates to the IconImage class to write the directory entry information as well as the image bits.

Figure 9 – Binary layout of .ICO file

Conclusion

Reading and writing Win32 resources is a non-trivial exercise in C++. Being able to pull it off in C# displays some of the power and flexibility of the .NET Framework. Resource management code should always be written carefully. Using the .NET Framework’s IDisposable class lends a helping hand by providing a common pattern for resource management. I hope that this exercise of walking through the development of the Icon Browser application was useful to you in helping to understand some of the services provided by the .NET Framework for writing code to interoperate with unmanaged code and resources.

EXE/DLL文件中的资源(位图、图标、字符串等)查看器 EXE/DLL文件中的资源(位图、图标、字符串等)查看器。以及版本信息等。代码较老,是VC6的项目工程,不过还是可用的,值得参考 立即下载

相关推荐

提取程序中的图标 vc源代码exeicon

提取exe中的图标的vc源代码

在C/C++中获取可执行文件的图标和信息

在写AutorunLoadViewer的过程中,需要能够获取可执行文件的图标和一些特定的文件信息(比如公司名还有文件版本.etc) 但是似乎MFC并没有提供现成的类库,于是只能自己通过API实现相应的功能 获取文件图标 关于如何获取文件图标,你可以很容易的在MSDN找到一个API——ExtracIcon 但是如果你仔细阅读文档说明,就会发现这个API并不符合我们的要

记事本 8214

数据库1:数据库创建与管理(头歌云课)

在 Windows 系统中,可以直接通过 SQLServer 的应用程序连接数据库,不过很多时候在生产环境下,我们需要通过命令行来连接数据库。两个数据库,数据库名分别为 TestDb 和 MyDb 的数据库,注意先后顺序。为了完成本关任务,你需要掌握:1.如何在 Linux 系统中连接 SQLServer 数据库,2.如何创建数据库。连接的数据库是本地数据库,用户名是 sa ,密码是 '

weixin_60530224的博客 2315

如何获取DLL,EXE中的图标

http://www.kennyandkarin.com/Kenny/CodeCorner/Tools/IconBrowser/ Icon Browser: An Exercise in Resource Management By Kenny Kerr, November 2001 Summary Info Prerequisites This article as

bitman的专栏 7121

汽车车牌识别系统实现(二)--车牌定位+代码实现

汽车车牌识别系统实现(二)-- 车牌定位 前言 本人大四计算机视觉处理方面菜鸟一枚,因个人兴趣和毕设的缘故,故而想学习计算机视觉方面的内容,有不正确的地方还等各位大神批评指正。 图像预处理 照相机获取到汽车车牌图像时,绝大多数情况下,图像里只存在一个车牌的情况是不太现实的,一幅图像里存在建筑物、树、其它汽车等等是很正常的;而且绝大多数都会存在噪声点,这种情况下就会对车牌定位和识别造成极大程度的干扰...

奋斗の博客 1万+

华为OD机试真题 2026-9-2【查找幸运数】

华为OD机试真题 新系统【查找幸运数】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【查找幸运数】多语言题解。

qq_45776114的博客 501

VC读取EXE文件的图标并保存

在网上搜索保存EXE文件图标的方法,找到许多文章,一大堆代码,10几个函数,一堆结构及定义,看着都头大。复制下来后,编译出错,少这个少那个的,捣鼓了半天时间都没搞好,终于放弃了。 就保存个图片,真有那么复杂吗!功夫不负有心人,终于找到了简单的方法,与大家分享下。 相关的结构还是要的: /******************************************************

VcTrue的专栏 3855

PyQt5开发编译器安装(PyCharm安装)

PyCharm 提供了最完整的 PyQt5 开发体验,特别是其集成的调试工具和 Qt Designer 支持,能显著提高开发效率。是最受欢迎和功能最完整的 IDE。它专门为 Python 开发优化,对 PyQt5 有很好的支持。右键运行该文件,如果出现窗口说明配置成功。对于 PyQt5 开发,

啊渊的专栏 421

C++ Builder 提取窗口图标

有时我们看到某个文件的图标很新颖,有心想保存下来,手头却找不合适的工具,能不能自己编个程序提取文件的图标呢?经过摸索,答案是肯定的,下面以C++ Builder为例,介绍文件图标提取过程。 Windows提供了一个API函数ExtractIcon,它能从指定的exe、dll、icon及其它含有图标的文件中提取图标,其原型如下: HICON ExtractIcon( HINSTAN

RunCode_Drive的专栏 791

DeepSeek与YOLO融合技术的微信小程序实现方案

本文介绍了一个基于微信小程序和Flask后端的智能图像检测系统。系统采用DeepSeek-7B进行自然语言理解,YOLOv8执行目标检测,并通过融合验证模块确保结果准确性。核心流程包括:用户通过小程序上传图片和文本需求,后端解析意图后执行目标检测,最后验证并返回结果。关键技术包括DeepSeek的指令理解、动态阈值调整和模型优化(ONNX、TensorRT)。系统适用于工业质检等场景,如"检测表面划痕",能自动识别目标并验证结果。部署需GPU服务器,并包含安全机制保障系统稳定运行。

老郑的博客 275

使用 MATLAB/Simulink 构建一个多时间尺度下的微电网经济运行优化策略模型

本文介绍了基于Simulink的多能互补微电网系统建模方法,重点关注多时间尺度下的经济运行优化策略。内容包括:系统背景与目标、微电网结构设计(光伏、风电、储能、柴油发电机等模块)、多时间尺度能量管理架构(日前优化、日内滚动优化、实时控制)的实现步骤,以及仿真运行与结果分析。教程详细说明了如何在Simulink中调用优化算法,设置仿真参数,并提供了进阶研究方向和资源推荐。该模型为研究微电网的经济运行和智能调度提供了完整的仿真平台解决方案。

amy_mhd的博客 173

WHY WORRY

WHY WORRY Nana Mouskour Baby I see this world has made you sad Some people can be bad The things they do, the things they say But baby I"ll wipe away those bitter tears I"ll chase away those restless

cenlop的专栏本 1264

CANape a2l文件的编辑教程

编辑a2l文件

wsq119的博客 1万+

Calling lua functions from .lua's using handles?

Calling lua functions from .lua's using handles? up vote0down votefavorite 5 I'm working on a small project trying to integrate lua with c++. My problem howeve

linuxheik的专栏 512

L2CAP 面向连接信道(CoC)在 BLE 中的应用:建立、流控与数据传输

L2CAP(逻辑链路控制与适配协议)是蓝牙协议栈中的核心层,位于基带层之上,为上层协议提供数据传输服务。在低功耗蓝牙(BLE)中,L2CAP面向连接信道(Connection-Oriented Channel, CoC) 是实现可靠数据传输的关键机制,广泛应用于健康监测、智能家居、工业控制等领域。

byte轻骑兵的技术小窝 3637

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

初识dll,在VS2010平台上创建并使用dll(revised)

一、为什么需要dll 代码复用是提高软件开发效率的重要途径。一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用。比较常见的例子是各种应用程序框架,如ATL、MFC等,它们都以源代码的形式发布。由于这种复用是“源码级别”的,源代码完全暴露给了程序员,因而称之为“白盒复用”。“白盒复用”的缺点比较多,总结起来有4点。 暴露了源代码;容易与程序员的“

Emilio563的博客 546

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

qtawesome的Icon Browser使用方法

浏览qtawesome内置的图标,这些图标可以在pyqt5中使用。 安装qtawesome pip install qtawesome 打开qtawesome内置的Icon Browser from qtawesome import icon_browser icon_browser.run() PyQt5中使用qtawesome的图标 from PyQt5.QWidgets import * import qtawesome as qta mw=QMainwindow() mw.setWindowI

weixin_43000172的博客 3153

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

提取Windows中系统自带的图标资源

提取Windows自带的图标资源,提取DLL/EXE中的资源。

witton的专栏 1万+

获取.exe/.dll/.icon文件的Icon图标资源

获取.exe/.dll/.icon文件的Icon图标资源

梦想博客 7473

DLL,OCX 文件预览图标的方法

DLL,OCX 文件预览图标的方法

qq_39021028的博客 545

C++获取dll文件中的icon

值得注意的是 phiconLarge的尺寸为32x32 phiconSmall的尺寸为16x16

qq_42877866的博客 706

wpf 加载资源html,C# – WPF – 添加图标后的项目大小(从资源加载图标或从项目EXE拉取)...

Edit1:已编辑的标题Edit2:添加了方法3Edit3:添加了方法4我正在创建一个非常小的应用程序/实用程序,总共只有20KB.我的包含各种尺寸的图标文件是40KB.我添加图标的方法是右键单击解决方案资源管理器中的项目,然后单击“现有项目…”,然后我再次右键单击我的项目,转到“属性” – > “应用程序”,在“图标和清单”下,我为整个项目选择了我的新图标.这样做会在我的所有表单,exe,...

weixin_31236309的博客 403

Win32Asm教程

  导言先来对这个教程做个小小的介绍。Win32Asm不是一个非常流行的编程语言,而且只有为数不多(但很好)的教程。大多数教程都集中在编程的win32部分(例如,WinAPI,标准Windows编程技术的使用等),而不是汇编语言本身,例如伪代码(opcodes),寄存器(registers)的使用等。虽然你能在其他教程中找到这些内容,但那些教程通常是解释Dos编程的。它当然可以帮你学习汇编语言,...

weixin_34054931的博客 299

LoadIcon() --加载一个图标资源

LoadIcon() 函数原型如下: ? 1 2 3 4 HICON LoadIcon(   HINSTANCE hInstance,   LPCTSTR lpIconName ); 该函数从与 hInstance 模块相关联的可执行文件中装入lpIc

whyrun的专栏 3万+

PE文件资源解析(一)资源类型的提取

这个界面相信作为软件开发人员来说,都不会陌生。 从本章节起,分篇介绍如何来开发一个属于自己的资源提取软件。资源的提取有2种,一种是通过WindowsAPI接口来实现资源类型的枚举,一种是通过解析PE文件结构来获取资源类型的枚举。PE文件解析方式将放在后面章节,这次首先以WindowsAPI方式来进行讲解:这里主要用到3个接口EnumResourceTypes、EnumResourceName...

老狼的专栏 2934
上一篇: Icons in Win32
下一篇: SeeDIB.exe Shows 16 and 32 Bits-Per-Pel Bitmap Formats
普通网友
博客等级 码龄22年 1万+粉丝 3156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值