Understanding resources in Visual Studio

10,826

Storage

For #1, the resource that you add is stored in XML format in a file named Resources.resx, typically located in the Properties subfolder of a WinForms or WPF application that is created using the default Visual Studio templates.

For #2 and #3, the resource (file) is included in the project (ie. the Visual Studio project knows about the file, it will be added to source control if that is applicable for the project, etc), the difference is in how the compiler includes the contents of the file as part of the resulting assembly. #2 is typically used for WPF applications; #3 for WinForms applications.


Access

#1 (Resources.resx)

The resources are accessed via an auto-generated class called Resources. For example, if you add a bitmap resource named MyBitmap you can access that as follows:

System.Drawing.Bitmap bitmap = Properties.Resources.MyBitmap;

#2 (Build Action = Resource)

The resources can be referenced from XAML (markup) or code. For XAML, several of the standard controls support resource references. For example, the Image control has a Source property that by default references an embedded resource. To reference a resource file named "wpf.jpg" contained in the root of your WPF project:

<Image Source="wpf.jpg" />

If the file was in a subfolder named "images":

<Image Source="images/wpf.jpg" />

To access these resources from code, you use the GetResourceStream method of the Application class, passing a reference to the desired resource in the form of a pack URI. Using the file in the above example:

Uri path = new Uri("images/wpf.jpg", UriKind.Relative);
StreamResourceInfo ri = Application.GetResourceStream(path);
Stream data = ri.Stream;

Once you have the stream you can do what you want with it.

#3 (Build Action = Embedded Resource)

You need to get a reference to the assembly containing the resource, then call the GetManifestResourceStream method to obtain a stream for it. What you do with the stream depends on the type of resource you're dealing with. For example, this will create a bitmap from a named resource:

Bitmap bitmap = new Bitmap(
    System.Reflection.Assembly.GetEntryAssembly()
    .GetManifestResourceStream("resourcename"));

Getting the right resource name can be tricky. It is generally a concatenation of the assembly name, and the folder and file name of the resource. For example, a file named "MyBitmap.bmp" in a folder named "Resources" in a project named "WindowsFormsApplication1" would be compiled to a resource named WindowsFormsApplication1.Resources.MyBitmap.bmp. That's the string you would pass to the GetManifestResourceStream method.


Adding new resources

As the resources are compiled into the assembly (EXE or DLL), adding new resources cannot be done without recompiling the assembly. The only programmatical way of doing this that I know of is to use a NuGet package called Mono.Cecil.

Share:
10,826
Wernfried Domscheit
Author by

Wernfried Domscheit

Updated on July 25, 2022

Comments

  • Wernfried Domscheit
    Wernfried Domscheit almost 2 years

    In Visual Studio I have several ways to include resources into my project:

    1. Solution Explorer → My Project → Right Click → Properties → Resources → Add Resource
    2. Copy file to solution directory → Solution Explorer → Show all Files → Right Click → Include in Project → Right Click → Properties → Build Action → Resource
    3. Copy file to solution directory → Solution Explorer → Show all Files → Right Click → Include in Project → Right Click → Properties → Build Action → Embedded Resource
    4. Some more?

    My questions are:

    • What are the differences of these resources?
    • How can I access them by code (C#)?
    • Is it possible to add new resources by code?