Q.

When building Windows forms I’ve noticed that my images don’t get updated in the built executable after they are modified on disk. This is even after a full rebuild of the executable.

With some tracking down I found that the selection of an image via a property page or via a custom designer results in designer code that looks something like this:

this.button1.Image = ((System.Drawing.Bitmap)(resources.GetObject("button1.Image")));

and the actual image appears to get sucked into the resx file like this:

<data name="button1.Image" type="System.Drawing.Bitmap, ..." mimetype="application/x-microsoft.net.object.bytearray.base64">
  <value>...base64-encoded data...</value>
</data>

The resx information doesn’t seem to include the original file information. This means that there is no automatic way of easily getting these resx files updated. This is a maintenance problem especially as the image count increases for a project or if the images are being provided by external parties.

My questions are:

Asked by Apolon Ivankovic. Answered by the Wonk on January 14, 2003

A.

When you add any kind of a resource, like an image, to a .resx file, the data for the resource is embedded directly into the .resx file and the original source of the data is never consulted again. This happens whether the .resx file is custom for the project or it’s a .resx file that goes along with a component class, e.g. a custom form, a custom control or a non-visual custom component. The upside is that if the source data goes away, the resource data is untouched. The downside is exactly what you point out: if the original data source is edited, the .resx file is not updated. This is further exacerbated by the fact that there are no tools in VS.NET to edit binary data once it’s been dropped into a .resx file. This last thing is the real killer and bears repeating: There is no way in VS.NET to edit binary data once it’s been added to a .resx file.

 

One work-around is to use manifest resources, which are files added to a project and marked as Embedded Resource. Those files get read and embedded as resources during each build and there are built in editors for most of the common files, e.g. bitmaps, XML, etc. Accessing a manifest resource is done at the assembly level. Assuming an embedded manifest resource called “Azul.jpg” and a default project namespace of “MyProjectNamespace”, you can load the raw bytes at runtime using a stream:

 

using System.IO;

 

public Form1() {

  ...

 

  // Get the currently executing assembly

  Assembly assem = Assembly.GetExecutingAssembly();

 

  // Get the stream that holds the resource

  // NOTE1: Make sure not to close this stream!

  // NOTE2: Also be very careful to match the case

  //        on the resource name itself

  Stream stream =

    assem.GetManifestResourceStream("MyProjectNamespace.Azul.jpg");

 

  // Load the bitmap from the stream

  this.BackgroundImage = new Bitmap(stream);

}

 

Some .NET types, like the bitmap provide shortcuts for reading from manifest resources, removing the need to open the stream separately:

 

// Load the bitmap directly from the manifest resources

// Use the namespace of the loading type as the prefix

this.BackgroundImage = new Bitmap(this.GetType(), "Azul.jpg");

 

I agree that this mechanism is not ideal compared to the convenience of setting resources from the Designer, but it is does allow for embedded resources that can be edited directly in VS.NET.

 

You current best bet for editing binary data in .resx files directly are 3rd-party .resx editors, like those provided in the References section.

References

Feedback

I have feedback on this Ask The Wonk answer