Search Forum
(57415 Postings)
Search Site/Articles

Archived Articles
712 Articles

C# Books
C# Consultants
What Is C#?
Download Compiler
Code Archive
Archived Articles
Advertise
Contribute
C# Jobs
Beginners Tutorial
C# Contractors
C# Consulting
Links
C# Manual
Contact Us
Legal

GoDiagram for .NET from Northwoods Software www.nwoods.com


              
Printable Version

The Mystery of Windows Resource Solved
By Lloyd Dupont

Download Source Code

Introduction

  In an Assembly one could put, beside an executable module, any number of any resource of any kind (image, sound, etc...), but how ? that's the mystery which is solved below !
  It is not as simple as java's Jar file, no it isn't. You couldn't simply add an image or anything else with a switch of the compiler. You should first build what is so called a ".resources" file, in which you put all your resources, each with a "key name" used to access it later.
after you could effectively add any number of them (that is of .resources) with something as simple as:
    csc /res:myresources.resources ...
The filename of the resource file is not innocent, it will be the symbolic name you will use to access it later. With the above mentioned myresources.resources you access it with the following code:
using System.Resources;
...
{
	// the assembly where is the resource
	Assembly resassembly = GetType().Assembly; 
	ResourceManager res = new ResourceManager("myresources", resassembly);
	...
    
	object myres = res.GetObject("key name");
}
As you could see, the ResourceManager automatically append ".resources" to your resource filename, it also add various things, such as "fr-FR.resources" when looking for internationalized file. so...
If you have a resource in another directory, or with another name, you better set its name like this:
    csc /res:../resdir/aresource.resources,resname.resources ...


Link a resource into your application

You should link your resource into your application for it to be able to retrieve the resource. You could either "embed" it (mean put it inside the executable), with the /res compiler flag or link to it (and put the file in the same directory) with /res, so you have the 2 following choice:
    csc /res:myResource.resources ...
    csc /link:myResource.resources ...
in the latter case you could upate the resource later without recompiling the application, that's the advantage.


Build a resource file

To build a resource file you have ResGen.exe which convert resx file and text format resource to .resources format. It is very usefull for text resources like this one:
// -- file MYSTRING.TXT --
error = you stupid customer not even able to do simple things
wintext = Hy guy "You = Best player in the universe" !
unimplemented = in full version for only 1.234.567 $
and you compile it with: resgen /compile MYSTRING.TXT myresource.resources
OR
you have the API and the very usefull System.Resources.ResourceWriter class.
OR
you have the ResBuilder tool...


Use ResBuilder to buid resources

For text resource Resgen.exe (in the SDK) is, by far, the most simple way but what about mixed resource files ?
Using the aforementionned API I write a simple tool ResBuilder.exe to build it. It take any number of configuration file and create resources files from them.
You invoke it like that: ResBuilder conf1 conf2 ...
here is a typical configuration file:
# some images
(
	# name of the destination file first..
	image.resources
		System.Drawing # lib where to find resource type...
	# now resources in the format (keyname type file)
	(ico    System.Drawing.Icon   editor.ico)
	(Bullet System.Drawing.Bitmap bullet.bmp)
)
# now some text !
(
	text.resources
	(hello string Hello)
	("good morning" string "Wellcome, gentlemen to this \"Modest House\"")
)
Simple, isn't it ? And you could store, with this tool, any serializable resource type having a constructor like Type(string).
You should indicate the assembly (different from mscrolib) where to find the given type as, Type.GetName(aTypeName); need it..


Internationalization

When you get a resource with new ResourceManager("myresources", resassembly); the .NET framwork look for international resource in subdirectory named as your local for a library name <applicationname>.<local>.resources.dll.

for example, if you live in France, and your application is called Demo, it will look in subdirectory fr-FR for a resource named Demo.fr-FR.resources.dll and will look in this assembly if there is a resource named myresource. Simple isn't it ? it will also look for the less local fr.
So you could always add resource later, well after the application is built....

to build these resource assembly, probably without any code, but only resources, you will need to use the assembly linker Al.exe like this:
    al /out:Demo.fr-FR.resources.dll /c:fr-FR /embed:text.fr-FR.resources