August 2006 Archives

How do you access resource files (bmp, mp3, etc) that are compiled into your Windows Forms executable? After googling the subject, the Assembly object's GetManifestResourceStream method seemed to be the solution. MSDN's entry on this subject makes it seem relatively simple. However, it took me over an hour to get it to work in my latest project. There are two things you must do in other to access an executable's resources:

  1. You must know the exact name of resource (mynamespace.resource.resourcename).

  2. You must embed the resource into your executable.

Accessing the resources means that you must have access to the executable's Assembly object. I cached this in the Form's Load event:

Assembly _assembly;
_assembly = Assembly.GetExecutingAssembly();

The image file that I was trying to access in my program was called Image1.bmp. I made a call to GetManifestResourceSteam like this:

imageStream = _assembly.GetManifestResourceStream(
    "ThumbnailPictureViewer.Image1.bmp");

The problem was that _imageStream was always returning NULL. Digging a little further, various articles mentioned that my decorated name might be incorrect. Perhaps I was using the wrong namespace, or the case sensitive name might be wrong? The only way to determine this was to use GetManifestResourceNames(). You can retrieve a collection of string resource names and dump them out to the console:

string[] names = _assembly.GetManifestResourceNames();
foreach (string name in names)
    System.Console.WriteLine(name);

The console showed me a few resource namespaces, but no embedded objects! Even had Image1.bmp clearly in my Solution Explorer, and in my Project properties, Resources tab, it never showed up. The trick in getting this to work is to make certain that Image1.bmp was set to Embedded Resource in the Properties window:

Build Action should be set to Embedded Resource

When you create resources in Visual Studio 2005, they are linked to your executable by default at compile time. This is a nice option if you want to keep the resource files separate from the .resx file, allowing other people to change them. If it needs to be accessed programatically with GetManifestResourceStream, it has to be Embedded into the .resx file. The only drawback here is that my Image resource can only be changed within Visual Studio 2005. Once I changed the Build Action to Embedded, I saw the correct name in the output window:

ThumbnailPictureViewer.resources.Image1.bmp

And then my code to load Image1.bmp into a Bitmap object worked successfully:

Stream _imageStream;
_imageStream = 
    _assembly.GetManifestResourceStream(
    "ThumbnailPictureViewer.resources.Image1.bmp");
Bitmap theDefaultImage = new Bitmap(_imageStream);

External Link:
MSDN summary on Linked vs. Embedded resources.

A new blog is launched out of a million other blogs. Why should you care? You probably won't unless you're a C# programmer or in need of a specific tool for your Windows computer. I'm using Attilan.com as an online log to record what I learn about Windows programming. Everyday I seem to learn something new, and unless I write it down, I'll forget it. This is better than a notebook because I can search it! I'll also be developing some new tools for Windows users, although you won't see the first of these until September 2006.

Fantastic Four 82: Inhumans in action
What does this have to do with the Inhumans? As a lifelong comic book fan, I bought the domain name attilan.com last year, after having used it on my own internal network at home. Attilan is the name of the city where the Inhumans live. Stan Lee and Jack Kirby created the Inhumans (a race of superhuman beings) in Fantastic Four #45, published in 1965. One of my favorite Fantastic Four covers (issue 82) shows the Inhumans in action beside the FF. The big kahuna flying next to the Human Torch is Black Bolt, their leader. On the ground you see Medusa (Black Bolt's wife), Gorgon, Karnak, and Crystal. Those names will mean something, something hopefully good and worthwhile, during the next few years. I won't bore you with too much comic book trivia, but occasionally I'll contribute Inhuman lore.

I take it as a sign of good luck that this blog is launching on August 28th, which is Jack Kirby's birthday.