Differences between .NET programs
.NET programs differ significantly from previous Windows applications in their executable file organization. Unlike traditional applications, .NET programs are organized using the MSIL language and require a Just-In-Time (JIT) compiler to compile them into native assembly instructions before execution, much like older VB programs—it's an interpreted execution process.
Corresponding to instructions is data, specifically static data or resources. .NET programs differ significantly from traditional programs in their approach to data. This article primarily analyzes the composition of .NET application resources and their operation.
Hosted Resource Description
Application resources mainly include strings, images, sounds, and videos, with the first two being the most commonly used. This article mainly provides a simple explanation based on experience in using BMP files. In the past, for MFC, resources were organized as .rc files. When the program used a resource, it used its resource ID number as an index, which was very inconvenient. Moreover, if you wanted to create a separate resource DLL file from the application, it was a very troublesome thing to do, both in terms of creation and use.
.NET programs have made improvements in these areas. First, during the design phase, it stores all resources uniformly in resource files, called managed resources. These resource files include two types: XML files and .resources files. When we program using .NET, especially VC.NET, we first create a form, add menus and buttons, and then add icons. At this point, a separate .resx file is generated corresponding to the form's name; this is the XML resource file.
XML resource files consist of XML tag text. Opening this form with a managed resource editor will display the icons and text you've added. Another type of resource file, .resources, stores resources in binary format. It is much smaller than XML resource files. This file doesn't exist during the design phase; it's only converted from an XML resource file to a .resources file when Visual Studio compiles the .NET application. Visual Studio also packages the resources from the XML resource file into the application and DLL files.
Why did Microsoft do this? Was it necessary to create two resource file formats? And why did Microsoft add small tools like the managed resource compiler in Visual Studio to achieve resource packaging? Why go through all this trouble? All these questions point to one profound explanation: to comply with the strategic needs of .NET.
Use of managed resources
To facilitate the use of these resources, you need to use the System::Resources assembly included in Visual Studio. The classes for manipulating .resx resource files are ResXResourceSet(), ResXResourceReader(), and ResXResourceWriter(). The classes for manipulating .resource files are ResourceSet(), ResourceReader(), and ResourceWriter(). These classes are primarily used for reading resources (the first two) and writing resources (the last one).
This involves directly manipulating resource files. Once resources are packaged into an EXE or DLL (called an assembly in .NET terminology), we use the ResourceManager class, which can only read resources. Here, we'll explain how to reference these resources. The simplest and most direct way is to reference them by name. For example, if there's an assembly a.dll that contains a r.resx file, and r.resx contains an img.bmp file, how do we use the img.bmp file from this assembly? This can be easily solved with a few lines of code:
System::Resources::ResourceManager ^res = nullptr;
Assembly ^Asm1 = Assembly::LoadFile("X:\\a.dll");
res = gcnew System::Resources::ResourceManager("ar",Asm1);
Image ^m=dynamic_cast(res->GetObject("img"));
Alternative Uses <br />In addition to some specific details that can be found on MSDN, here are some unconventional uses.
While it's logical to put all resources into a .resx file and then package it into the assembly, is it feasible to put resources (specifically bmp files) directly into the assembly without going through the packaging step? The answer is yes. In fact, Microsoft does just that. During control development, if you want to give a control an icon that can be displayed in the Visual Studio toolbox, you must give the icon (e.g., a bmp file) the same name as the control: (assembly name).(control name).bmp, and then set this icon as the linker's embedded managed resource file. The specific method is to right-click on the project name in the Solution Explorer -> Properties, select Linker -> Input in the left column of the pop-up dialog box, and then enter the resources to be embedded in the Embedded Managed Resource File field. If there are multiple resources to be embedded, separate them with commas. After setting it up, compile, and then the remaining issue is referencing. Here, referencing isn't done in the conventional way, but rather using the Stream class in the System::IO assembly and the GetManifestResourceStream method of the Assembly class. The specific referencing method is as follows:
Assembly ^assembly = Assembly::GetExecutingAssembly();
System::IO::Stream ^strm =assembly->GetManifestResourceStream("img.bmp");
Image ^m=System::Drawing::Image::FromStream(strm);
This section only explains the direct embedding of BMP files. If readers are interested, they can also try other resources.
It's clear that this method is more direct, but there's no data to prove that its speed is significantly different from the conventional method. From a development perspective, whether embedding or referencing, this method is relatively simple. Of course, from a management perspective, this approach is not advisable; efficiency and standardization are often an irreconcilable contradiction.
Postscript: Choosing Development Tools
Below, we'll introduce two tools frequently used in .NET application development, and how to use them:
The first tool is the MSIL disassembler that comes with Visual Studio. It can display assemblies in a tree-like list and disassemble assemblies into IL instruction files. This article mainly uses it to view the names of managed resources so that they can be referenced elsewhere. From File -> Open, select a DLL file containing managed resources, click Open, and double-click the manifest node. A new window will pop up, displaying descriptions of each referencing assembly. Search for ".mresource" to find the managed resource filename.
The second tool is the renowned Reflector, written by an Microsoft employee. It's an indispensable tool for decompiling and cracking .NET programs. In this article, we'll mainly use it to check if the resource files have been correctly embedded directly into the assembly. This tool is even simpler to use; after opening the assembly file, simply click the Resources node. If the resources have already been embedded, they will be directly present in this directory.