Create resource files for .NET apps

You can include resources, such as strings, images, or object data, in resources files to make them easily available to your application. The .NET Framework offers five ways to create resources files:

  • Create a text file that contains string resources. You can use Resource File Generator (resgen.exe) to convert the text file into a binary resource (.resources) file. You can then embed the binary resource file in an application executable or an application library by using a language compiler, or you can embed it in a satellite assembly by using Assembly Linker (Al.exe). For more information, see the Resources in text files section.

  • Create an XML resource (.resx) file that contains string, image, or object data. You can use Resource File Generator (resgen.exe) to convert the .resx file into a binary resource (.resources) file. You can then embed the binary resource file in an application executable or an application library by using a language compiler, or you can embed it in a satellite assembly by using Assembly Linker (Al.exe). For more information, see the Resources in .resx Files section.

  • Create an XML resource (.resx) file programmatically by using types in the System.Resources namespace. You can create a .resx file, enumerate its resources, and retrieve specific resources by name. For more information, see Working with .resx Files Programmatically.

  • Create a binary resource (.resources) file programmatically. You can then embed the file in an application executable or an application library by using a language compiler, or you can embed it in a satellite assembly by using Assembly Linker (Al.exe). For more information, see the Resources in .resources Files section.

  • Use Visual Studio to create a resource file and include it in your project. Visual Studio provides a resource editor that lets you add, delete, and modify resources. At compile time, the resource file is automatically converted to a binary .resources file and embedded in an application assembly or satellite assembly. For more information, see the Resource files in Visual Studio section.

Resources in text files

You can use text (.txt or .restext) files to store string resources only. For non-string resources, use .resx files or create them programmatically. Text files that contain string resources have the following format:

# This is an optional comment.
name = value

; This is another optional comment.
name = value

; The following supports conditional compilation if X is defined.
#ifdef X
name1=value1
name2=value2
#endif

# The following supports conditional compilation if Y is undefined.
#if !Y
name1=value1
name2=value2
#endif

The resource file format of .txt and .restext files is identical. The .restext file extension merely serves to make text files immediately identifiable as text-based resource files.

String resources appear as name/value pairs, where name is a string that identifies the resource, and value is the resource string that is returned when you pass name to a resource retrieval method such as ResourceManager.GetString. name and value must be separated by an equal sign (=). For example:

FileMenuName=File
EditMenuName=Edit
ViewMenuName=View
HelpMenuName=Help

Caution

Do not use resource files to store passwords, security-sensitive information, or private data.

Empty strings (that is, a resource whose value is String.Empty) are permitted in text files. For example:

EmptyString=

Starting with .NET Framework 4.5 and in all versions of .NET Core, text files support conditional compilation with the #ifdefsymbol... #endif and #if !symbol... #endif constructs. You can then use the /define switch with Resource File Generator (resgen.exe) to define symbols. Each resource requires its own #ifdefsymbol... #endif or #if !symbol... #endif construct. If you use an #ifdef statement and symbol is defined, the associated resource is included in the .resources file; otherwise, it is not included. If you use an #if ! statement and symbol is not defined, the associated resource is included in the .resources file; otherwise, it is not included.

Comments are optional in text files and are preceded either by a semicolon (;) or by a pound sign (#) at the beginning of a line. Lines that contain comments can be placed anywhere in the file. Comments are not included in a compiled .resources file that is created by using Resource File Generator (resgen.exe).

Any blank lines in the text files are considered to be white space and are ignored.

The following example defines two string resources named OKButton and CancelButton.

#Define resources for buttons in the user interface.
OKButton=OK
CancelButton=Cancel

If the text file contains duplicate occurrences of name, Resource File Generator (resgen.exe) displays a warning and ignores the second name.

value cannot contain new line characters, but you can use C language-style escape characters such as \n to represent a new line and \t to represent a tab. You can also include a backslash character if it is escaped (for example, "\\"). In addition, an empty string is permitted.

Save resources in text file format by using UTF-8 encoding or UTF-16 encoding in either little-endian or big-endian byte order. However, Resource File Generator (resgen.exe), which converts a .txt file to a .resources file, treats files as UTF-8 by default. If you want Resgen.exe to recognize a file that was encoded using UTF-16, you must include a Unicode byte order mark (U+FEFF) at the beginning of the file.

To embed a resource file in text format into a .NET assembly, you must convert the file to a binary resource (.resources) file by using Resource File Generator (resgen.exe). You can then embed the .resources file in a .NET assembly by using a language compiler or embed it in a satellite assembly by using Assembly Linker (Al.exe).

The following example uses a resource file in text format named GreetingResources.txt for a simple "Hello World" console application. The text file defines two strings, prompt and greeting, that prompt the user to enter their name and display a greeting.

# GreetingResources.txt
# A resource file in text format for a "Hello World" application.
#
# Initial prompt to the user.
prompt=Enter your name:
# Format string to display the result.
greeting=Hello, {0}!

The text file is converted to a .resources file by using the following command:

resgen GreetingResources.txt

The following example shows the source code for a console application that uses the .resources file to display messages to the user.

using System;
using System.Reflection;
using System.Resources;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("GreetingResources",
                               typeof(Example).Assembly);
      Console.Write(rm.GetString("prompt"));
      string name = Console.ReadLine();
      Console.WriteLine(rm.GetString("greeting"), name);
   }
}
// The example displays output like the following:
//       Enter your name: Wilberforce
//       Hello, Wilberforce!
Imports System.Reflection
Imports System.Resources

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("GreetingResources",
                                      GetType(Example).Assembly())
        Console.Write(rm.GetString("prompt"))
        Dim name As String = Console.ReadLine()
        Console.WriteLine(rm.GetString("greeting"), name)
    End Sub
End Module
' The example displays output like the following:
'       Enter your name: Wilberforce
'       Hello, Wilberforce!

If you are using Visual Basic, and the source code file is named Greeting.vb, the following command creates an executable file that includes the embedded .resources file:

vbc greeting.vb -resource:GreetingResources.resources

If you are using C#, and the source code file is named Greeting.cs, the following command creates an executable file that includes the embedded .resources file:

csc greeting.cs -resource:GreetingResources.resources

Resources in .resx files

Unlike text files, which can only store string resources, XML resource (.resx) files can store strings, binary data such as images, icons, and audio clips, and programmatic objects. A .resx file contains a standard header, which describes the format of the resource entries and specifies the versioning information for the XML that is used to parse the data. The resource file data follows the XML header. Each data item consists of a name/value pair that is contained in a data tag. Its name attribute defines the resource name, and the nested value tag contains the resource value. For string data, the value tag contains the string.

For example, the following data tag defines a string resource named prompt whose value is "Enter your name:".

<data name="prompt" xml:space="preserve">
  <value>Enter your name:</value>
</data>

Warning

Do not use resource files to store passwords, security-sensitive information, or private data.

For resource objects, the data tag includes a type attribute that indicates the data type of the resource. For objects that consist of binary data, the data tag also includes a mimetype attribute, which indicates the base64 type of the binary data.

Note

All .resx files use a binary serialization formatter to generate and parse the binary data for a specified type. As a result, a .resx file can become invalid if the binary serialization format for an object changes in an incompatible way.

The following example shows a portion of a .resx file that includes an Int32 resource and a bitmap image.

<data name="i1" type="System.Int32, mscorlib">
  <value>20</value>
</data>

<data name="flag" type="System.Drawing.Bitmap, System.Drawing,
    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    mimetype="application/x-microsoft.net.object.bytearray.base64">
  <value>
    AAEAAAD/////AQAAAAAAAAAMAgAAADtTeX…
  </value>
</data>

Important

Because .resx files must consist of well-formed XML in a predefined format, we do not recommend working with .resx files manually, particularly when the .resx files contain resources other than strings. Instead, Visual Studio provides a transparent interface for creating and manipulating .resx files. For more information, see the Resource files in Visual Studio section. You can also create and manipulate .resx files programmatically. For more information, see Work with .resx files programmatically.

Resources in .resources files

You can use the System.Resources.ResourceWriter class to programmatically create a binary resource (.resources) file directly from code. You can also use Resource File Generator (resgen.exe) to create a .resources file from a text file or a .resx file. The .resources file can contain binary data (byte arrays) and object data in addition to string data. Programmatically creating a .resources file requires the following steps:

  1. Create a ResourceWriter object with a unique file name. You can do this by specifying either a file name or a file stream to a ResourceWriter class constructor.

  2. Call one of the overloads of the ResourceWriter.AddResource method for each named resource to add to the file. The resource can be a string, an object, or a collection of binary data (a byte array).

  3. Call the ResourceWriter.Close method to write the resources to the file and to close the ResourceWriter object.

Note

Do not use resource files to store passwords, security-sensitive information, or private data.

The following example programmatically creates a .resources file named CarResources.resources that stores six strings, an icon, and two application-defined objects (two Automobile objects). The Automobile class, which is defined and instantiated in the example, is tagged with the SerializableAttribute attribute, which allows it to be persisted by the binary serialization formatter.

using System;
using System.Drawing;
using System.Resources;

[Serializable()] public class Automobile
{
   private string carMake;
   private string carModel;
   private int carYear;
   private int carDoors;
   private int carCylinders;

   public Automobile(string make, string model, int year) :
                     this(make, model, year, 0, 0)
   { }

   public Automobile(string make, string model, int year,
                     int doors, int cylinders)
   {
      this.carMake = make;
      this.carModel = model;
      this.carYear = year;
      this.carDoors = doors;
      this.carCylinders = cylinders;
   }

   public string Make {
      get { return this.carMake; }
   }

   public string Model {
      get { return this.carModel; }
   }

   public int Year {
      get { return this.carYear; }
   }

   public int Doors {
      get {
         return this.carDoors; }
   }

   public int Cylinders {
      get {
         return this.carCylinders; }
   }
}

public class Example
{
   public static void Main()
   {
      // Instantiate an Automobile object.
      Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
      Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
      // Define a resource file named CarResources.resx.
      using (ResourceWriter rw = new ResourceWriter(@".\CarResources.resources"))
      {
         rw.AddResource("Title", "Classic American Cars");
         rw.AddResource("HeaderString1", "Make");
         rw.AddResource("HeaderString2", "Model");
         rw.AddResource("HeaderString3", "Year");
         rw.AddResource("HeaderString4", "Doors");
         rw.AddResource("HeaderString5", "Cylinders");
         rw.AddResource("Information", SystemIcons.Information);
         rw.AddResource("EarlyAuto1", car1);
         rw.AddResource("EarlyAuto2", car2);
      }
   }
}
Imports System.Drawing
Imports System.Resources

<Serializable()> Public Class Automobile
    Private carMake As String
    Private carModel As String
    Private carYear As Integer
    Private carDoors AS Integer
    Private carCylinders As Integer

    Public Sub New(make As String, model As String, year As Integer)
        Me.New(make, model, year, 0, 0)
    End Sub

    Public Sub New(make As String, model As String, year As Integer,
                   doors As Integer, cylinders As Integer)
        Me.carMake = make
        Me.carModel = model
        Me.carYear = year
        Me.carDoors = doors
        Me.carCylinders = cylinders
    End Sub

    Public ReadOnly Property Make As String
        Get
            Return Me.carMake
        End Get
    End Property

    Public ReadOnly Property Model As String
        Get
            Return Me.carModel
        End Get
    End Property

    Public ReadOnly Property Year As Integer
        Get
            Return Me.carYear
        End Get
    End Property

    Public ReadOnly Property Doors As Integer
        Get
            Return Me.carDoors
        End Get
    End Property

    Public ReadOnly Property Cylinders As Integer
        Get
            Return Me.carCylinders
        End Get
    End Property
End Class

Module Example
    Public Sub Main()
        ' Instantiate an Automobile object.
        Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
        Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
        ' Define a resource file named CarResources.resx.
        Using rw As New ResourceWriter(".\CarResources.resources")
            rw.AddResource("Title", "Classic American Cars")
            rw.AddResource("HeaderString1", "Make")
            rw.AddResource("HeaderString2", "Model")
            rw.AddResource("HeaderString3", "Year")
            rw.AddResource("HeaderString4", "Doors")
            rw.AddResource("HeaderString5", "Cylinders")
            rw.AddResource("Information", SystemIcons.Information)
            rw.AddResource("EarlyAuto1", car1)
            rw.AddResource("EarlyAuto2", car2)
        End Using
    End Sub
End Module

After you create the .resources file, you can embed it in a run-time executable or library by including the language compiler's /resource switch, or embed it in a satellite assembly by using Assembly Linker (Al.exe).

Resource files in Visual Studio

When you add a resource file to your Visual Studio project, Visual Studio creates a .resx file in the project directory. Visual Studio provides resource editors that enable you to add strings, images, and binary objects. Because the editors are designed to handle static data only, they cannot be used to store programmatic objects; you must write object data to either a .resx file or to a .resources file programmatically. For more information, see Work with .resx files programmatically and the Resources in .resources files section.

If you're adding localized resources, give them the same root file name as the main resource file. You should also designate their culture in the file name. For example, if you add a resource file named Resources.resx, you might also create resource files named Resources.en-US.resx and Resources.fr-FR.resx to hold localized resources for the English (United States) and French (France) cultures, respectively. You should also designate your application's default culture. This is the culture whose resources are used if no localized resources for a particular culture can be found.

To specify the default culture, in Solution Explorer in Visual Studio:

  • Open the project properties, right-click the project and select Properties (or Alt + Enter when project is selected).
  • Select the Package tab.
  • In the General area, select the appropriate language/culture from the Assembly neutral language control.
  • Save your changes.

At compile time, Visual Studio first converts the .resx files in a project to binary resource (.resources) files and stores them in a subdirectory of the project's obj directory. Visual Studio embeds any resource files that do not contain localized resources in the main assembly that is generated by the project. If any resource files contain localized resources, Visual Studio embeds them in separate satellite assemblies for each localized culture. It then stores each satellite assembly in a directory whose name corresponds to the localized culture. For example, localized English (United States) resources are stored in a satellite assembly in the en-US subdirectory.

See also