The Basics of Resource Files in .Net 1.1

 

Summary

We learned what manifest or managed resources are, stepped through what Visual Studio .Net does with images it uses at design time and runtime, (hopefully) learned how to use a few new utilities to work with resources and looked over some code that uses resource file for images and strings in a few different ways.

 

After making it all the way through this article and playing with the included code, you will see that the basics of resource files in .Net are really easy to use.  At the beginning of my research for this article I did not know too much about resource files, but after a little reading of the documentation and some searching on the internet, it wasn’t long before I had a directory full of useful utilities and also a couple that I wrote myself, of course this was just the basics – next will be the advanced…

 

Download the Code

Sample Application - VB.Net version

Sample Application - C# version

Sample Application - C++ version

Utility - RFC and WinResourceFileCreator

Utility - RW and WinResourceWrapper

 

Contents

Introduction

What is a resource?

A Step by Step look at how VS.Net uses resource files

Resource file formats in .Net

            Text Format (*.txt)

            Resx Format (*.resx)

            Resources Format (*.resources)

Sample Application

Embedded Resources

ResourceManager

Using ResourceFileWrapper (RW)

 

Introduction

The purpose of this article is to give the reader a better understanding of some common ways to use resource files in .Net applications.  The goal of this article is to answer the following questions:

·         What are resources?

·         What are resource files?

·         How do you create resource files?

·         How do you use resource files?

·         How do you write code that uses resource files?

In order to answer these questions and give the reader a better understanding of resources in .Net version 1.1 we will walk through a small exercise with VS.Net and really looking to see what goes on behind the scenes as well as introduce several utility applications that will help you work with resources.  Then we will go through the code of a sample application that uses images and strings from resource files in order to see some real code that uses resource files.

 

In this article, I am not going to cover any ASP.Net or satellite assembly specific topics, I think they would be better explained in another article.

 

What is a resource?

Some where along the line in learning .Net I am sure you learned the major parts of an assembly: module, metadata, manifest, IL Code and resources.  It is the resources part that I want to focus on in this paper (if you want to learn more about the others I recommend Jeff Richter’s Applied .Net Framework Programming or for even deeper specifics you might try Serge Lidin’s Inside Microsoft .Net IL Assembler).  With .Net assemblies there are two types of resources: managed and unmanaged.  Of the two types of resources, I want to focus on the managed resources.  Unmanaged resources are things like an icon for your application to use in Windows Explorer (Richter mentions unmanaged resource in Chapter 2, page 56 of his book).

 

The types of resources we will be covering are know as “manifest resources”.  The Common Language Infrastructure (CLI) : Partition II Medatdata Section 6.2.2 Manifest Resources states:

 

A manifest resource is simply a named item of data associated with an assembly.  A manifest resource is introduced using the .mresource directive, which adds the manifest resource to the assembly manifest begun by a preceding .assembly declaration.

 

What the CLI definition means, is that resources are non-executable data or objects (think string and images) that an application uses. Resource files are simply containers for these resources, typically in .Net these resource files are embedded in the final assembly and kept track of in the assembly’s manifest as .mresources entries.

 

Things that you might want to keep in a resource file include such things as strings (any text displayed to the user is a great candidate), images, icons, or audio files.  Placing these resources in a resource file and not “hard coding” them in your applications can:

·         improve your flexibility in future changes to any text strings in an application

·         improve the time it would take to localize an application to another language

·         allow resources to always be available for your application at runtime

 

One alternative, that you are probably familiar with, to using resource files or “hard coding” is to use external data files that you load at runtime.  This does give you the flexibility of being able to change the contents easily, but once your application is shipped, your user might delete this external data file or worse not have access to the file, leaving your application in a less than optimum state (might crash or might just look bad depending on the situation).

 

A good example of putting an image into a resource file, instead of loading it from the file system at runtime, is a splash screen. The purpose of a splash screen is not just branding of the application, but it is to divert the user’s attention from the actual load time of the application (user friendliness reasons). If the image file (not using a resource file in this situation) that the splash form uses on load is not there or is corrupt, then this splash screen isn’t going to make your customers happy even before the application starts.  Now if you put your splash screen image in a resource file or embed it in your assembly, the splash form will always be able to load the image – leaving you with one less place for things to go wrong on the user’s machine (ie. Production).

 

A Step by Step look at how VS.Net uses resource files

In order to better understand the simple situation of a background image on a form and how resource files can help you out, let’s do a step by step look at how Visual Studio .Net takes a background image and puts it in a resource file for you (whether you know it or not).

 

Visual Studio.Net uses resource files when you choose an image file to use as a background image of a form and other similar image type displays (such as a PictureBox) by setting the BackgroundImage property.

 

In order to get a good understanding of how resource files are used, lets go through a detailed example of setting a background image on a form and see what exactly VS.Net does for us in the background.

 

1.      Start VS.Net and create a new Windows Forms application (I will be using C#, but you can use anything you want).  Name the solution BackgroundImageExample.

2.      In the solution explorer double click on Form1 to view the form designer.

3.      In the designer right-click and choose properties

4.      Find the BackgroundImage property, click on the ellipse button and find a jpg file to use as your background and click OK

 

Figure 1

 

5.       The form designer should now load the image into the designer automatically, press CTRL+F5 to run the application and see if it works

 

Ok so it works, right?  That was pretty easy, but what actually happened to load that image? In order to understand what just took place within so few easy steps, I want to bring a few things to your attention. First of all, notice in the property window for the BackgroundImage (figure 1) it did not put the path to the actual file that you chose, it put System.Drawing.Bitmap, which is the type of object being used as the background but what about that file you chose? Well, let’s find out where it went.

 

1.      On the Project menu, click the Show All Files item

2.      Now go to the solution explorer and you should see a plus beside Form1

 

Figure 2

 

3.      Click on the plus sign and you will see Form1’s resource file (figure 2).

4.      Double-click on Form1.resx and you will see the Resx editor interface (figure 3).  Notice the entry $this.BackgroundImage with a type of System.Drawing.Bitmap, this is the image you chose as your background image.

 

Figure 3

 

 

In order to verify that this is indeed your image, let’s check the resx file using another tool. 

 

1.      Go to http://www.aisto.com/roeder/dotnet/ and download Resourcer for .Net (you might as well download reflector too if you don’t already have it).

2.      Once you have downloaded Resourcer, I suggest you extract the exe and put it (or a shortcut to it) in your SendTo folder C:\Documents and Settings\<yourusername>\SendTo  - this will allow you to right click in Windows Explorer and send a resource file to Resourcer.

3.      Open Windows Explorer (Windows Key + E), find your BackgroundImageExample project folder.

4.      Find the file name Form1.resx, right-click on it and choose SendTo and then choose Resourcer (or you can open Resourcer and find the Form1.resx file yourself)

5.      Find the resource name $this.BackgroundImage and click on it.  The image should show in the bottom panel of Resourcer (figure 4) – you might have to move the splitter to see the image better.

 

Figure 4

 

Now we have seen how VS.Net will take a file and insert it into a resource file, verified that it does load at runtime as well as verified that it is in the resource file – now let’s see where it is in the exe.

 

Here is were I suggest you add Ildasm.exe to your SendTo menu as well.  You can find Ildasm under the C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin directory.

 

1.      Open Windows Explorer and find your BackgroundImageExample solution and locate the exe, it will either be one or two levels under a bin or debug directory (depending on what .Net language you are using).

2.      Right click on the exe and choose SendTo and then choose Ildasm (or open Ildasm and find the exe yourself) (shown in figure 5 below).

 

Figure 5

3.      Double-click on the MANIFEST node of the tree and you will see the text representation of the manifest for this exe.

4.      Scroll down the manifest and you will see and entry that looks like figure 6.

 

.mresource public BackgroundImageExample.Form1.resources

{

}

Figure 6

 

This shows us the manifest resource entry for the BackgroundImageExample.Form1.resources file, but what does that file look like? We looked at the Form1.resx file, not Form1.resources file.  Since we can’t actually see the contents of that file in Ildasm’s UI, let’s decompile the exe and get a look at that resources file.

 

Now I have another tool for you to add to your SendTo directory to make your life better… VS.Net Command Prompt Here, download it from http://www.larkware.com/Articles/VS.NETCommandPromptHere.html

 

It will give you an .inf file, which you right click on and choose install.  This utility will add another item to your right click menu in the Windows Explorer that will open a command window with the proper .Net paths set for the SDK tools at the directory you click on in Windows Explorer (faster than going to the start prompt … VS.Net tools… then finding the path via walking the directory).

 

Now let’s tear that exe apart

1.      Open windows Explorer (if you don’t still have it open) and find your BackgroundImageExample solution and locate the exe.

2.      This time in the left pane of the windows explorer right click on the directory the exe is in and choose the new item VS.Net 2003 CMD Prompt Here.  This will open a command window with the path already set to the directory the exe is in (or you could go to your start button, programs, Visual Studio 2003, Visual Studio 2003 tools, command prompt and then walk to the directory the BackgroundImageExample.exe is in).  See Figure 7 below.

Figure 7

 

3.      Type the following:  ildasm BackgroundImageExample.exe /out:source.il

4.      You should now have three new files in that directory, one of which is the extracted BackgroundImageExample.Form1.resources that we saw was embedded in our assembly.

5.      Right-click on the BackgroundImageExample.Form1.resources file and SendTo and resourcer.  You will see it is basically the same file as the Form1.Resx (figure 4) resource file was.  The only difference that I see between the two files is that the resources file size is quite a bit smaller than the resx file, just as you would suspect since it is the compiled version of the corresponding resx (xml) file.

 

So far we have tracked down the flow of the actual image file from the setting of the BackgrounImage property to the runtime binary, but now how does the image get loaded from this resource file into the background of the form?  Let’s look at the code:

1.      Go back to your Solution explorer in VS.Net and double-click on Form1 and then right click and choose View Code.

2.      Scroll down and find the region that says “Windows Form Designer generated code” and open that region up.

3.      If you look at the InitializeComponent method you will see the following code (I trimmed out some namespace info to shorten the text):

 

 

ResourceManager resources = new ResourceManager(typeof(Form1));

this.BackgroundImage = ((Image)(resources.GetObject("$this.BackgroundImage")));

 

Figure 8

 

The code shown in figure 8 are the two lines that are needed to retrieve the background image out of the resource file – at design time as well as runtime.  We will see how to use the ResourceManager class later in another example.

 

NOTE: since the image file is copied into the resource file at the time you chose the image, the background image (now a stream in the resource file or a Base64 Encoded byte array depending on how you look at it) will not reflect any changes made to the original image file – there is NO link between the two representations of that image.  In order to update the resource version of the file you will need to remove the resource, compile and add the resource back, the next time you compile it should have the new resource.

 

So now we have seen that the following takes place in VS.Net when you set the BackgroundImage property of a form.

1.      VS.Net copies the chosen file into its resource file (resx file)

2.      VS.Net loads that image from the resource file at design time so the form designer will reflect the new settings

3.      When you compile the application, VS.Net will create a .resources file and embed that file into the final assembly

4.      The same code that the designer used (in InitializeComponent) will also run at runtime retrieving the image stream from the resource section of the assembly.

 

Resource file formats in .Net

There are two main formats to resource files in .Net, resx and resources.  If you use the ResGen.exe utility to create a resource file, you also have the option of using a text file.  Both the text and resx file formats are sort of an intermediate representation of the resource file before it gets compiled into a resources file.  Unfortunately, in VS.Net 2003 there isn’t a way to add resources to a resources file in a one step manner (although VS.Net will take care of compiling the resx file format into a resources file for you – giving you the ability to handle strings in a “one-step” process).

 

Text Format (*.txt)

As mentioned above, you can create a text file and use it as a resource file for your application.  Of course the only type of resource you can represent in a text file is strings and the file must be saved in one of three encodings UTF-16 (little-endian or big-endian) or UTF-8.  All resources in the text file need to be in the following format:

name=value

If you need to have comments in your text file that are not to be used as a resource you can use the ‘;’ semi-colon or ‘#’ number sign characters at the beginning of the line to exclude it from resource creation.

 

Since keeping strings in a text file and being able to use that text file in creating resources is so useful, I added this capability to the ResourceFileCreator and RFC utilities that we will talk about later.

 

Figure 9 shows an example of a text file full of name/value pairs that can be added to a resource file.

 

Figure 9

As you can see in figure 9 the text file has a comment as the first line and then five very simple name value items.  I should mention the fact that there are no spaces in my names.  Spaces are supported in resource names (after all it is just a string key to a dictionary of resources – more or less), but in the examples later we will be generating a wrapper class that will expose a property (which cannot have spaces) with the same name as the resource.

 

There are a couple of ways we can convert a text file to a resx format resource file: ResGen and the RFC utility.

 

Using ResGen.exe to create a Resx file

 

 

ResGen C:\images\descriptions.txt C:\images\descriptions.resx

 

Figure 10

 

Using RFC.exe to create a Resx file

 

 

RFC /f:C:\images\descriptions.txt /o:C:\images\descriptions.resx

 

Figure 11

 

If you open up descriptions.resx using Resourcer you will see all the name value pairs have been added (Figure 12).

 

Figure 12

 

You could also create a .resources file using both of these tools by just changing the extension of the output file to be .resources instead of .resx.

 

How do these utilities create the resource file? First thing that happens is a check to see what type of resource file is to be created (resx or resources).  This is necessary because they use different writers (ResXResourceWriter or ResourceWriter), which we’ll learn how to use in the next couple of sections.  Other than determining which resource writer to use, the text file needs to be parsed for name/value pairs.  The way I do it in the RFC utility is by using the following RegEx expression: (^[^;#\s][^=]*)=([^=;#]*)\r\n

 

The RegEx engine will return matches containing name/value pairs, which are then enumerated through and written to the resource file.

 

ResX Format (*.resx)

Resx files are Xml files that comply to the Microsoft ResX Schema.  There are a few ways to get a resource into a resx file that we will go through: VS.Net IDE, ResXWriter Class, ResXGen.exe, RFC.exe (or WinResourceFileCreator.exe) or Resourcer.

 

Using Visual Studio .Net

VS.Net has an item type that will add a .Resx file to your project.  Project menu -> Add New Item -> Assembly Resource File (figure 13).

 

Figure 13

 

As with most XML file in Visual Studio, you will have two views of the data, one is the text (think angle brackets) and the other is more of a grid view (figure 3).  This grid view is nice for adding strings to your resx file, but it will not be able to help you with adding images.  In order to add other resource types you will need to use one of the other ways of creating/editing resx files.

 

Using the System.Resources.ResXWriter Class

This is the class you would use to write a resx file (and is what is used in the other utilities that we’ll go into next).  One thing to note about this class is that it resides in the System.Windows.Forms.dll (the rest of the System.Resources namespace resides in mscorlib.dll).  If you look at the code in ResourceFileCreator (part of the download) you might notice that the adding of resources to a resource file using ResourceWriter and ResXWriter are the same because they both implement the IResourceWriter interface.  Typically if you are creating a resource file programmatically the process is like this:

1.      Create a backing stream to used with the resource writer

2.      Create the resource writer (passing the backing stream to it)

3.      Use the AddResource() method to add resources to the writer

4.      Once you are done adding resources, call Generate() – to make sure all resources are added to the output stream (think Flush()).

5.      Close the resource writer (this method will make sure the backing stream is closed as well).

 

Using ResXGen

RegXGen is a tutorial utility application that comes with the .Net SDK.  It is usually installed at: C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Samples\Tutorials\resourcesandlocalization\resxgen

 

This means if you have the SDK installed, then you have this utility and its code.

 

 

ResXGen /i:c:\images\discoverypark1.jpg /n:DiscoveryPark1 /o:C:\images\images.resx

 

Figure 14

 

ResXGen has the following command line arguments:

/i:

Input image filename to convert

/o:

Output .resx filename

/n:

Name of the resource

/s

Displays the regx schema

Figure 15

 

Using RFC

This is one of the utilities included with the source code of this article.  The RFC and WinResourceFileCreator can both be used to create resource files, but currently will not append to an existing resource file (Resourcer is better for this).

 

 

RFC /f:C:\images\discoverypark1.jpg /o:C:\images\images.resx

 

Figure 16

 

Using Resourcer

This is by far the easiest of the options.

 

Open Resourcer, Choose New on the File Menu, choose Insert Files on the Edit menu, browse to the image you want to add and click OK, click the save button, choose the resource file extension you want, give it a name, and click OK. 

 

Resources Format (*.resources)

Resources files are binary resource files that are usually created by VS.Net at compile time, but can be created programmatically using the ResourceWriter class, RFC.exe, ResGen.exe or Resourcer.

 

Using the System.Resources.ResourceWriter Class

This is the Writer class that will write a binary resource file.  The process is exactly the same as the ResXWriter (see above section titled *.resx).

 

Using RFC

This utility will also create a resources file in the same manner as it creates a resx file depending on what file extension is on the output file.

 

 

RFC /f:C:\images\discoverypark1.jpg /o:C:\images\images.resources

 

Figure 17

 

Using ResGen

Since this utility is designed to convert from one resource format to another, you will need to already have all the resources in a text file or a resx file, which can be done by using one of the options above.

 

 

ResGen images.resx images.resources

 

Figure 18

 

Using Resourcer

This again is by far the easiest of the options and is exactly the same as adding items to a resx file (see above), just choose to save the file with a .resources extension instead of .resx.

 

Sample application

Now that you have an idea of what resources are and how to put them in resource files as well as the different formats of resource files, let’s look at an example.  I have included a sample application in the code for this article.  There is a VB.Net version, C# version and a Managed C++ version. The Managed C++ version does not have the embedded image examples, only the resource manager and resource file wrapper examples.

 

In order to demonstrate some of the different ways to include resources in your assembly as well as different manners of accessing resources at runtime, I have put together a simple Windows Forms application that uses some photos and some text resources.  The sample application is a simple photo album.  The idea is to have a photo and its description shown and the ability to step through the set of photos by using previous and next buttons (figure 19).

 

A few things to note about the sample application

 

In order to include the different approaches to embedding images and the different code used to access the manifest resources you will need to take the following items into account:

 

·         In order to change the manner of which resources are used/accessed you will need to comment/uncomment the proper methods in the btnNext_Click() and btnPrevious_Click() event handlers.

 

·         The sample application has both embedded images as well as a resource file that also contains the same images.

Figure 19

 

Embedded Resources

One of the options we have to include images (or any file) in a project is to include them as embedded resources.  In the sample application I have embedded five images in the application using Visual Studio.  In order to do this, all you need to do is add the items to your project and in the properties window (Figure 20) set the Build Action to Embedded Resource.

 

Figure 20

 

When you add resources in this manner, they will be added at compile time to your assembly with a resource name the same as the file name you added (with the default namespace of the application pre-pended to the file name).  For example in figure 21 you can see the manifest (from ILDasm) that has all the embedded images listed with their names as manifest resource (.mresource) items.

 

Figure 21

 

With embedded images, we have two choices of retrieving our images from the assembly manifest.  In the sample code these choices are represented in the ChangeImageUsingManifestResourceStream() and ChangeImageBitmapConstructor() methods.

 

First we’ll look at the version that uses a resource stream (figure 22).  I have cleaned out the code that deals with the string resource right now because it is not embedded in this case (it is in the Images.resources file) – only the image file.

 

private void ChangeImageUsingManifestResourceStream(int intImageIndex)

{

  Assembly assembly = Assembly.GetExecutingAssembly();

                    

  string strImageName = String.Format("HenleyCSharp.DiscoveryPark{0}.JPG", intImageIndex.ToString());

 

  System.IO.Stream objImageStream = assembly.GetManifestResourceStream(strImageName);

 

                    

  _pbImage.Image = System.Drawing.Image.FromStream(objImageStream);

      

}

Figure 22

 

Since our resources are part of the compiled assembly we need to get a reference to the executing assembly.  Next (and very important) we need to have the resource name in order to look up the resource in the manifest.  In this case I know the namespace and the file name (derived from the current index of the photos) is HenleyCSharp.DiscoveryPark1.JPG (if the current index is 1).  Remember this is a photo album application, in which the current index keeps track of which image and description to show the user.  After the resource name is derived we can now look the resource up in the manifest.  In this case we know the resource is an image object so we need to use the GetManifestResourceStream() method to get a Stream object back.  Lucky enough for us Image has a static (shared) method named FromStream() that takes a stream in and will return a valid Image object.

 

Now let’s look at a slightly different way of getting an image resource out of the assembly’s manifest. 

 

private void ChangeImageBitmapConstructor(int intImageIndex)

{

                    

  string strImageName = String.Format("DiscoveryPark{0}.JPG", intImageIndex.ToString());

                    

  _pbImage.Image = new Bitmap(this.GetType(), strImageName);

      

}

Figure 23

 

In figure 23 you might have noticed that we aren’t dealing with the Assembly directly.  This is due to the Bitmap constructor that takes a Type and a string to return an image. What the Bitmap constructor is doing behind the scenes is basically what we did in the last example (figure 22). You might also notice the namespace “HenleyCSharp” is not pre-pended to the image name.  The code that we have written in figure 23 makes it look as if the Bitmap object is keeping track of all our resources for us (which it really isn’t – the assembly is).  In this example the Bitmap class is doing the manual work of getting the image from the assembly manifest as a stream and loading it for us.

 

With just these two embedded image examples I am sure you can see some advantages to being able to embed a file into an assembly and easily access it as a stream.  The ResourceFileWrapper utility that I have included with this code uses this technique to keep the XSLT files as resources embedded in the assembly.

 

Now let’s look at accessing resources that we put into a resource file and embedded into our assembly (either by using VS.Net, al.exe or your compiler of choice).

 

ResourceManager Class

Earlier we discussed the different formats of resource files and ways to create them, now let’s see how we put those resource files into our assembly and how we can access those resources once they are in our assembly by using the ResourceManager class.

 

In order to add or link a resource file to an assembly you need to already have a .resources file (see above on how to do that). If you have added all the resources to the resx that is in your VS.Net project you will not need to worry about this because VS.Net will take care of that for you.

 

Using VS.Net to do it for you

Here you have two options: 1.  Use Resourcer to add your resources to an existing resx file in your project.  2.  Create an resx file outside of your project, add all your resources to it, then add that resx file to your project (via Add Existing Item).  When you compile your application VS.Net will take care of the rest for you.

 

Using command line utilities

Here you have two choices: 1. AL.exe 2. csc.exe or vbc.exe.  I will leave this as an exercise to the reader if they choose to dive into the manual linking.  See the links provided in the Utilities section of documentation for the compilers and the linker.  You might also want to check out Chapter 2 of Richter’s book.

 

Now that we know how to add our resources to our assembly (via a resource file) we now need to access our resources in our code, so let’s get back to the sample application.

 

The method ChangeImage is the method we want to look at now.  In the case of the sample application I have a resources file that contains all the images and descriptions named images.resx.

 

private void ChangeImage(int intImageIndex)

{

  Assembly assembly = Assembly.GetExecutingAssembly();

  ResourceManager  resources = new ResourceManager(

"HenleyCSharp.Images", assembly);

                                 

  string strImageName = String.Format(

    "DiscoveryPark{0}", intImageIndex.ToString());

  string strImageDescription = String.Format(

    "DiscoveryPark{0}_Description" ,intImageIndex.ToString());

                                 

  _pbImage.Image = (System.Drawing.Image)resources.GetObject(

    strImageName);

  _lblDescription.Text = resources.GetString(strImageDescription);

}

Figure 24

 

As you can see in figure 24 the constructor of the ResourceManager takes a string and an assembly object.  The string that we are passing (“HenleyCSharp.Images”) is knows as the base name of the resource.  You can derive this base name two ways: 1. Add the default namespace of the project and the name of the resources file together 2.  Open up the assembly and look for it.

 

If you use the Reflector utility (see Utilities section on where to get it), you can see the resources under the assembly much the same as we did earlier (figure 6) when we were tracking down what VS.Net does with image resources.  The advantage to using Reflector in this case is the ease at seeing what is in that resource set called (in this case) HenleyCSharp.Images[.resources].  (figure 25).  The .resources extension is assumed so the base name doesn’t need to include it.

Figure 25

 

Once we have a ResourceManager loaded with our resource file contents we can access the contents with their resource name.  The two methods that are used to access these resources are the GetString() and GetObject() methods.  The GetString() of course takes in a resource name and returns the string representation of that resource.  The GetObject() method will return an object which leaves it to us to cast that resource to the object that we need.  In the sample application it is an Image.

 

Using ResourceFileWrapper (RW) Utility

Creating a wrapper class for your resource file using the ResourceFileWrapper and using that wrapper class.

 

In order to simplify the extraction of resources from a resource manager and to have strongly typed access to those resources, I create what I call a resource file wrapper.  This wrapper class contains the logic to read in the resources from the assembly and exposes each resource in that resource set as a strongly typed property on the wrapper class.  Let’s look at the images wrapper for the sample application.

 

In order to create this wrapper, I used the ResourceFileWrapper utility command line application named RW.  Once I had all the images and the text file with the descriptions added to the resx file, the creation of this wrapper class was easy.

 

 

RW /r:C:\images\images.resx /l:cs /n:HenleyCSharp