Click here to Skip to main content
Click here to Skip to main content

Using Resources in Your Application Part I - Simple Embedding.

By , 8 Mar 2003
 

Article1.jpg

Introduction

The .NET framework provides a rich feature set for working with resources in your application. Using resources in your application can help with packaging, deployment, maintenance, globalization and localization. Over the course of this multipart series, you will learn how to use resources and what they can do for you in your own applications.

What are resources?

Simply stated, resources are anything that your application uses to operate that is not considered executable code. Resource examples include icons, graphic files, strings, and objects. For each of these file types, the framework has provided methods to load these directly from their file. Given that, you may ask yourself "why do I need to use resources?". There are indeed a few very good reasons. First, you are able to group all your resources in one place. This keeps users from going to your applications directory and deleting files they have no business deleting. Second, it allows you to localize your application, provided, you do the work up front, to not use hard coded references to images and text in your application. Once you have the framework in place, you can distribute your application in a new language with relative ease.

Using the code

There are two applications included in this example. The first, the CreateResource is used to generate .resource files that can then be embedded into an application. The second is a simple example that demonstrates how to extract resources that have been embedded in your application assembly. These examples show how resources work in the .NET framework world. If you have Visual Studio, these features may come for free as part of that package.

Creating your resource file

Creating a resource file is relatively simple. The .NET framework provides all the functionality needed to take multiple resources and combine them into one resource file that can be included in your applications assembly. The ResourceWriter class implements the functionality described by the IResourceWriter interface, and is the primary class used when creating resources programmatically. To use the class you simply fire up the constructor, passing in the filename of what will be the resulting resource file.

IResourceWriter writer = new ResourceWriter(OutputFileName);

Resources can then be added to the resource file using the method IResourceWriter.AddResource (name, resource), where name is the string identifier that will be used to locate the resource and resource is either a Byte array, String, or object. Resources are written to the resource file in one of two ways. The first is after a call to IResourceWriter.Generate(). The second is after a call to IResourceWriter.Close() is made. Closing a resource file with pending additions will automatically call the Generate() method.

Armed with this knowledge you can easily construct an application to take the grunt work out of creating resource files. I have included one example with this article that I use on a regular basis to generate simple resource files that I can then embed into application assemblies. It reads in a text file containing the names of files to include as resources. It has the ability to process icons, bitmaps, strings, gifs, jpegs, and text files containing name-value pairs representing string resources.

CreateResource starts by initializing itself with an input file and output file. The input file is a simple text file containing files, one per line, which will be included as resources in the specified output resource file. If an output file is not specified, a default file name is chosen.

  ...
  if (args.Length == 0){
    Console.WriteLine("CreateResource <inputfile> <outputfile>");
    return;
  }
  
  if (!File.Exists(args[0])){
    Console.WriteLine(string.Format("File {0} does not exist", args[0]));
  }else{
    string OutputFileName = "";
    if (args.Length == 1){
      OutputFileName = "app.resources";
    }
    string InputFileName = args[0];
  ...

A new ResourceWriter is created returning an IResourceWriter interface. The input file is then opened with each line read in. An object is created based on the file type (with the exception of a text file) and added to the resource file using IResourceWriter.AddResource(). Text files passed in are opened and each name value pair specified is added to the resource file individually.

  ...
  IResourceWriter writer = new ResourceWriter(OutputFileName);
  StreamReader f = new StreamReader(InputFileName);
  string line = "";
  while (f.Peek() > -1){
    line = f.ReadLine(); 
    if (line.Length > 0){
      string ext = line.Substring(line.Length-3, 3);
      object res = null;
  
      string name = "";
      if (ext=="ico"){
        res = new Icon(line);
        name = line.Substring(0, - (ext.Length + 1)).ToUpper();
        writer.AddResource(name, res);
      }else if (ext=="bmp" | ext=="gif" | ext=="jpg"){
        res = Image.FromFile(line);
        name = line.Substring(0, line.Length - (ext.Length + 1)).ToUpper();
        writer.AddResource(name, res);
      }else if (ext=="txt"){
        //extract name value pairs
        StreamReader rf = new StreamReader(line);
        string resLine = "";
        while (rf.Peek() > -1){
          resLine = rf.ReadLine();
          if ( !resLine.StartsWith("[") && !resLine.StartsWith(";")){
            int i = resLine.IndexOf("=");
            name = resLine.Substring(0, i);
            i++;
            res =  resLine.Substring(i, resLine.Length - i);
            writer.AddResource(name, res);
          }
        }
      }
    }
  }
  writer.Close();

Once the input file has been processed, ResourceWriter.Close() is called to commit the changes to the resource file. It is that easy. You can use the compiled sample by typing CreateResource <inputfile> <outputfile> from the command line.

Embedding your resource file in your assembly

The resulting output file from running CreateResource is a single resource file containing the entire file specified in the input text file. In order to use this file in your application, you will need to embedded it as a resource in your assembly. Using the .NET framework C# compiler, it is done using the /resource:<filename> switch.

csc /out:main.exe /target:exe 
    /DEBUG+ /DEBUG:full /INCREMENTAL+ /resource:app.resources mainform.cs

Using your embedded resources in your application

Now that the resources have been embedded into the assembly, using them is a simple task. The second example application, ShowResources, shows how the ResourceManager class can be used to extract resources for use in an application.

The application opens the embedded resource by constructing a ResourceManager class. In this case, the parameters passed in are the base name of the resource (in our case app) file that was embedded and the currently running assembly. Notice we do not have to specify the .resource extension. The runtime takes care of that for us.

ResourceManager rm = new ResourceManager("app", this.GetType().Assembly);

To extract specific resources, the ResourceManager provides two methods, GetObject() and GetString(). You use GetObject() to extract anything from the resource file that is not a string. Using the methods are fairly simple. You specify the name specified when adding the resource and you get back the object.

      //a jpeg
      PictureBox jpg = new PictureBox();
      jpg.Dock = DockStyle.Top;
      jpg.Image = (Image)rm.GetObject("CODEPROJECT");
      ...
      //a bitmap
      PictureBox bm = new PictureBox();
      bm.Dock = DockStyle.Top;
      bm.Image = (Image)rm.GetObject("BACKGROUND");
      ...
      //strings
      listBox = new ListBox();
      listBox.Dock = DockStyle.Top;
      listBox.Height = 150;
      listBox.Items.Add(rm.GetString("rhyme1"));
      listBox.Items.Add(rm.GetString("rhyme3"));
      ...

In closing

You can see how easy it is to create and embed resources in your application. In part 2 we will explore more advanced uses of resources. If you have any questions about the included code or applications, please let me know.

Upcoming articles

  • Part 2 - Satellite Assemblies and Localization

History

  • 03/06/2003 - Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Dan Logan
Web Developer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow use resourde with audio, video, database files in C# application?memberhitsmly19 Oct '04 - 21:41 
Ciao!
 
In VB, Resource Editor can manages *.bmp, *.ico, *.cur, string table and other data defined by user, these is *.wav, *.avi, *.mdb.
Can you tell me how to create and use resource with audio, video and database files in C# application.
 
Thank you in advance.
 
PS:
 
I have tried on your sample "Using Resource in Your application PartI - Simple Embedding".
 
I created a file resource named "res.resource" by VS.NEt tool called resEditor in SDK, I tried on it in CSharpDevelop, it run clearly, but in VS.NET,it has the following error:
 
"An unhandled exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.dll.
Additional info: Counld not find any resources appropriate for the specified culture (or the neutral)in the given assembly. Make sure "res.resource" was correctly embedded or linked into assembly 'rs1' basename: app locationInfo: resource file name: res.resource assembly: rs1, Version = 1.0.1753.5075, culture = neutral, PublicKeyToken = Null".
 
I used the code:
ResourceManager rm = new ResourceManager(this.GetType().Assembly);
pb.Image = (Image)rm.GetObject("bmp");
 
I don't understand. What happened? D'Oh! | :doh: Can you explain it for me? I looking forward to your answer. Thanks a lot.
 
Hitsmly.

 
Hitsmly
AnswerRe: How use resourde with audio, video, database files in C# application?memberFlora PL14 Dec '04 - 1:43 
Have you tried using assembly with name projectname.filename ?
 
eg. ResourceManager rm = new ResourceManager("rs1.res");
 

GeneralGood jobmemberAntonio Barros4 Sep '04 - 7:26 
Hi
 
I've liked very much your article and the other you have published.
Did you have idea to write the other multi-part series ?
 
Thank you
A.Barros
GeneralRe: Good jobmemberDan Logan8 Sep '04 - 2:22 
Thanks Antonio. I appreciate you reading what I have written. I do plan on writting the second part of this, I just need to get a block of time to do it. Thanks again.
QuestionHow create .res files?memberLYASasha15 Apr '04 - 6:44 
Smile | :) I want to add in res-file some text.
How I made do itSmile | :)
 
LYASasha
GeneralUsing WAV resourcesmemberDave Hall15 Oct '03 - 19:31 
I haven't tried your examples yet, but the concept seems pretty reasonable as I read the article. I am interested in using WAV files as resources. It's pretty clear how to get any arbitrary binary file into a resource, and then extract it from the resource back to the original file as in the dll example submitted by leppie. I'm wondering if you might include an example of using the PlaySound() API for playing a sound as a resource rather than as a file. I'll probably mess with it myself and post a follow up here if I figure out how to do it. (By the way, any idea when that second article might come out?)
 
Here's a first crack at it. I haven't compiled or tested any of it yet though...

public class SoundResource
{
[Flags]
public enum PlaySoundFlags : int
{
SND_SYNC = 0x00000000, /* play synchronously (default) */
SND_ASYNC = 0x00000001, /* play asynchronously */
SND_NODEFAULT = 0x00000002, /* silence (!default) if sound not found */
SND_MEMORY = 0x00000004, /* pszSound points to a memory file */
SND_LOOP = 0x00000008, /* loop the sound until next sndPlaySound */
SND_NOSTOP = 0x00000010, /* don't stop any currently playing sound */
SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
SND_ALIAS = 0x00010000, /* name is a registry alias */
SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
SND_FILENAME = 0x00020000, /* name is file name */
SND_RESOURCE = 0x00040004 /* name is resource name or atom */
}
 
[DllImport("coredll")]
private static extern bool PlaySound( string szSound, IntPtr hMod, PlaySoundFlags flags );
 
// TODO: Describe how to determine valid resource name(s) for the parameter
// and how to determine which resources in the project are really WAV files...
public bool Play(String resourceName)
{
return PlaySound(resourceName,
IntPtr.Zero,
PlaySoundFlags.SND_RESOURCE |
PlaySoundFlags.SND_SYNC |
PlaySoundFlags.SND_NODEFAULT
);
}
}


GeneralRe: Using WAV resourcesmemberPiledriver19757 Sep '05 - 9:37 
Hey buddy, did you ever get wav resources in a dll working? If so can you mail me the sln? meyer_phillip@hotmail.com Thanks.
GeneralOT: Bobby ShaftoememberChristian Tratz13 Mar '03 - 5:54 
Cryptonomicon is one of my favourite books Wink | ;)
 
But I always imagined him to look a little bit different than the CP-bunny (what's his name again?)
 
-Chris
GeneralEmbedding filesmemberleppie10 Mar '03 - 8:55 
Hi there
 
Nice article, but a powerfull feature is to add files too, but like your method goes these files cant just be cast via the ResourceManager. Here is some code you could add to you article before moving on the the next part.
 
1. Add any file to you project, and set it to embedded resource under properties. Of course like you did, you can just do this manaully as well.
 
2. For the extraction bit, here's some sample code code (I use this in my nBASS project to embed required unmanaged dll's, and for a template access DB in my MyDUMeter article). Just note that the projects default namespace is added to the resource name:
 
<font  size=2 face="Courier New"><font color="#0000FF">private static void </font><font color="#000000">CheckDLL</font>(<font color="#000000">string dllfilename</font>)
{
   <font color="#0000FF">if </font>(!(<font color="#000000">System</font>.<font color="#000000">IO</font>.<font color="#000000">File</font>.<font color="#000000">Exists</font>(<font color="#000000">dllfilename</font>)))
   {
      <font color="#000000">System</font>.<font color="#000000">IO</font>.<font color="#000000">Stream s </font>= <font color="#000000">Assembly</font>.<font color="#000000">GetExecutingAssembly</font>().
         <font color="#000000">GetManifestResourceStream</font>(<font color="#FF8000">"nBASS." </font>+ <font color="#000000">dllfilename</font>);
      <font color="#000000">System</font>.<font color="#000000">IO</font>.<font color="#000000">Stream r </font>= <font color="#000000">System</font>.<font color="#000000">IO</font>.<font color="#000000">File</font>.<font color="#000000">Create</font>(<font color="#000000">dllfilename</font>);
      <font color="#0000FF">int </font><font color="#000000">len </font>= <font color="#FF0000">8192</font>;
      <font color="#000000">byte</font>[] <font color="#000000">buffer </font>= <font color="#0000FF">new </font><font color="#000000">byte</font>[<font color="#000000">len</font>];
      <font color="#0000FF">while </font>(<font color="#000000">len </font>> <font color="#FF0000">0</font>)
      {
         <font color="#000000">len </font>= <font color="#000000">s</font>.<font color="#000000">Read</font>(<font color="#000000">buffer</font>, <font color="#FF0000">0</font>, <font color="#000000">len</font>);
         <font color="#000000">r</font>.<font color="#000000">Write</font>(<font color="#000000">buffer</font>, <font color="#FF0000">0</font>, <font color="#000000">len</font>);
      }
      <font color="#000000">r</font>.<font color="#000000">Close</font>();
      <font color="#000000">s</font>.<font color="#000000">Close</font>();
   }
}
</font>

 
I rated this article 2 by mistake. It deserves more. I wanted to get to the second page... - vjedlicka 3:33 25 Nov '02
GeneralRe: Embedding filesmemberDan Logan10 Mar '03 - 18:02 
Thanks for the excellent suggestion. I had considered doing just what you suggested, but I wanted to keep the article simple for part one. I plan to include embedding files when I get into satellite assemblies and localization. I feel that it will make a stronger impact this way. BTW, your DUMeter is pretty cool.

GeneralRe: Embedding filesmemberNemanja Trifunovic5 Sep '03 - 9:50 
Excellent! You saved my day. Thanks.
GeneralRe: Embedding filesmemberleppie5 Sep '03 - 10:04 
Nemanja Trifunovic wrote:
You saved my day.
 
You cant save mine, can you? Laugh | :laugh:
 
leppie::AllocCPArticle("Zee blog");
GeneralRe: Embedding filesmemberDan'M19 Nov '07 - 5:43 
Hi leppie,
It's great code for reading embedded resource files. I used it in my project. But can you please , tell me something more that now how to open that file by its default programme or in explorer ? D'Oh! | :doh: (I have a .zip file as a embedded resource).I am very new to using this things. :-> I just need a littlebit more help if you can explain it more . :->
 
Thanks,
Dan
GeneralNicememberChopper10 Mar '03 - 2:01 
Good articleSmile | :)
 
I only want to know how to do all this stuff in VC++ 6 provided .NET framework is available.
 
Any suggestions?

 
Regards,
Vitaly Tomilov
 

Professional tooltips for all development platforms Free on www.Tooltips.NET


GeneralRe: NicememberDan Logan10 Mar '03 - 17:48 
I wish I could offer something more, but I don't have a very strong C++ background. What I can say is that the code you will find in the examples describes how to use the framework classes. I know that the managed C++ compiler that ships with the .NET framework has access to all the same classes, so, you should be able to port the example if you have the C++ know how.
 

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 9 Mar 2003
Article Copyright 2003 by Dan Logan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid