Working with .resx Files Programmatically - .NET (2023)

  • Article


This article applies to .NET Framework. For information that applies to .NET 5+ (including .NET Core), see Resources in .resx files.

Because XML resource (.resx) files must consist of well-defined XML, including a header that must follow a specific schema followed by data in name/value pairs, you may find that creating these files manually is error-prone. As an alternative, you can create .resx files programmatically by using types and members in the .NET Class Library. You can also use the .NET Class Library to retrieve resources that are stored in .resx files. This article explains how you can use the types and members in the System.Resources namespace to work with .resx files.

This article discusses working with XML (.resx) files that contain resources. For information on working with binary resource files that have been embedded in assemblies, see ResourceManager.


There are also ways to work with .resx files other than programmatically. When you add a resource file to a Visual Studio project, Visual Studio provides an interface for creating and maintaining a .resx file, and automatically converts the .resx file to a .resources file at compile time. You can also use a text editor to manipulate a .resx file directly. However, to avoid corrupting the file, be careful not to modify any binary information that is stored in the file.

Create a .resx file

You can use the System.Resources.ResXResourceWriter class to create a .resx file programmatically, by following these steps:

  1. Instantiate a ResXResourceWriter object by calling the ResXResourceWriter(String) method and supplying the name of the .resx file. The file name must include the .resx extension. If you instantiate the ResXResourceWriter object in a using block, you do not explicitly have to call the ResXResourceWriter.Close method in step 3.

  2. Call the ResXResourceWriter.AddResource method for each resource you want to add to the file. Use the overloads of this method to add string, object, and binary (byte array) data. If the resource is an object, it must be serializable.

  3. Call the ResXResourceWriter.Close method to generate the resource file and to release all resources. If the ResXResourceWriter object was created within a using block, resources are written to the .resx file and the resources used by the ResXResourceWriter object are released at the end of the using block.

The resulting .resx file has the appropriate header and a data tag for each resource added by the ResXResourceWriter.AddResource method.


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

The following example creates a .resx file named CarResources.resx 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.

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 (ResXResourceWriter resx = new ResXResourceWriter(@".\CarResources.resx")) { resx.AddResource("Title", "Classic American Cars"); resx.AddResource("HeaderString1", "Make"); resx.AddResource("HeaderString2", "Model"); resx.AddResource("HeaderString3", "Year"); resx.AddResource("HeaderString4", "Doors"); resx.AddResource("HeaderString5", "Cylinders"); resx.AddResource("Information", SystemIcons.Information); resx.AddResource("EarlyAuto1", car1); resx.AddResource("EarlyAuto2", car2); } }}
Imports System.DrawingImports 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 PropertyEnd ClassModule 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 resx As New ResXResourceWriter(".\CarResources.resx") resx.AddResource("Title", "Classic American Cars") resx.AddResource("HeaderString1", "Make") resx.AddResource("HeaderString2", "Model") resx.AddResource("HeaderString3", "Year") resx.AddResource("HeaderString4", "Doors") resx.AddResource("HeaderString5", "Cylinders") resx.AddResource("Information", SystemIcons.Information) resx.AddResource("EarlyAuto1", car1) resx.AddResource("EarlyAuto2", car2) End Using End SubEnd Module


You can also use Visual Studio to create .resx files. At compile time, Visual Studio uses the Resource File Generator (Resgen.exe) to convert the .resx file to a binary resource (.resources) file, and also embeds it in either an application assembly or a satellite assembly.

You cannot embed a .resx file in a runtime executable or compile it into a satellite assembly. You must convert your .resx file into a binary resource (.resources) file by using the Resource File Generator (Resgen.exe). The resulting .resources file can then be embedded in an application assembly or a satellite assembly. For more information, see Create resource files.

Enumerate resources

In some cases, you may want to retrieve all resources, instead of a specific resource, from a .resx file. To do this, you can use the System.Resources.ResXResourceReader class, which provides an enumerator for all resources in the .resx file. The System.Resources.ResXResourceReader class implements IDictionaryEnumerator, which returns a DictionaryEntry object that represents a particular resource for each iteration of the loop. Its DictionaryEntry.Key property returns the resource's key, and its DictionaryEntry.Value property returns the resource's value.

The following example creates a ResXResourceReader object for the CarResources.resx file created in the previous example and iterates through the resource file. It adds the two Automobile objects that are defined in the resource file to a System.Collections.Generic.List<T> object, and it adds five of the six strings to a SortedList object. The values in the SortedList object are converted to a parameter array, which is used to display column headings to the console. The Automobile property values are also displayed to the console.

using System;using System.Collections;using System.Collections.Generic;using System.Resources;public class Example{ public static void Main() { string resxFile = @".\CarResources.resx"; List<Automobile> autos = new List<Automobile>(); SortedList headers = new SortedList(); using (ResXResourceReader resxReader = new ResXResourceReader(resxFile)) { foreach (DictionaryEntry entry in resxReader) { if (((string) entry.Key).StartsWith("EarlyAuto")) autos.Add((Automobile) entry.Value); else if (((string) entry.Key).StartsWith("Header")) headers.Add((string) entry.Key, (string) entry.Value); } } string[] headerColumns = new string[headers.Count]; headers.GetValueList().CopyTo(headerColumns, 0); Console.WriteLine("{0,-8} {1,-10} {2,-4} {3,-5} {4,-9}\n", headerColumns); foreach (var auto in autos) Console.WriteLine("{0,-8} {1,-10} {2,4} {3,5} {4,9}", auto.Make, auto.Model, auto.Year, auto.Doors, auto.Cylinders); }}// The example displays the following output:// Make Model Year Doors Cylinders//// Ford Model N 1906 0 4// Ford Model T 1909 2 4
Imports System.CollectionsImports System.Collections.GenericImports System.ResourcesModule Example Public Sub Main() Dim resxFile As String = ".\CarResources.resx" Dim autos As New List(Of Automobile) Dim headers As New SortedList() Using resxReader As New ResXResourceReader(resxFile) For Each entry As DictionaryEntry In resxReader If CType(entry.Key, String).StartsWith("EarlyAuto") Then autos.Add(CType(entry.Value, Automobile)) Else If CType(entry.Key, String).StartsWith("Header") Then headers.Add(CType(entry.Key, String), CType(entry.Value, String)) End If Next End Using Dim headerColumns(headers.Count - 1) As String headers.GetValueList().CopyTo(headerColumns, 0) Console.WriteLine("{0,-8} {1,-10} {2,-4} {3,-5} {4,-9}", headerColumns) Console.WriteLine() For Each auto In autos Console.WriteLine("{0,-8} {1,-10} {2,4} {3,5} {4,9}", auto.Make, auto.Model, auto.Year, auto.Doors, auto.Cylinders) Next End SubEnd Module' The example displays the following output:' Make Model Year Doors Cylinders' ' Ford Model N 1906 0 4' Ford Model T 1909 2 4

Retrieve a specific resource

In addition to enumerating the items in a .resx file, you can retrieve a specific resource by name by using the System.Resources.ResXResourceSet class. The ResourceSet.GetString(String) method retrieves the value of a named string resource. The ResourceSet.GetObject(String) method retrieves the value of a named object or binary data. The method returns an object that must then be cast (in C#) or converted (in Visual Basic) to an object of the appropriate type.

The following example retrieves a form's caption string and icon by their resource names. It also retrieves the application-defined Automobile objects used in the previous example and displays them in a DataGridView control.

using System;using System.Collections.Generic;using System.Drawing;using System.Resources;using System.Windows.Forms;public class CarDisplayApp : Form{ private const string resxFile = @".\CarResources.resx"; Automobile[] cars; public static void Main() { CarDisplayApp app = new CarDisplayApp(); Application.Run(app); } public CarDisplayApp() { // Instantiate controls. PictureBox pictureBox = new PictureBox(); pictureBox.Location = new Point(10, 10); this.Controls.Add(pictureBox); DataGridView grid = new DataGridView(); grid.Location = new Point(10, 60); this.Controls.Add(grid); // Get resources from .resx file. using (ResXResourceSet resxSet = new ResXResourceSet(resxFile)) { // Retrieve the string resource for the title. this.Text = resxSet.GetString("Title"); // Retrieve the image. Icon image = (Icon) resxSet.GetObject("Information", true); if (image != null) pictureBox.Image = image.ToBitmap(); // Retrieve Automobile objects. List<Automobile> carList = new List<Automobile>(); string resName = "EarlyAuto"; Automobile auto; int ctr = 1; do { auto = (Automobile) resxSet.GetObject(resName + ctr.ToString()); ctr++; if (auto != null) carList.Add(auto); } while (auto != null); cars = carList.ToArray(); grid.DataSource = cars; } }}
Imports System.Collections.GenericImports System.DrawingImports System.ResourcesImports System.Windows.FormsPublic Class CarDisplayApp : Inherits Form Private Const resxFile As String = ".\CarResources.resx" Dim cars() As Automobile Public Shared Sub Main() Dim app As New CarDisplayApp() Application.Run(app) End Sub Public Sub New() ' Instantiate controls. Dim pictureBox As New PictureBox() pictureBox.Location = New Point(10, 10) Me.Controls.Add(pictureBox) Dim grid As New DataGridView() grid.Location = New Point(10, 60) Me.Controls.Add(grid) ' Get resources from .resx file. Using resxSet As New ResXResourceSet(resxFile) ' Retrieve the string resource for the title. Me.Text = resxSet.GetString("Title") ' Retrieve the image. Dim image As Icon = CType(resxSet.GetObject("Information", True), Icon) If image IsNot Nothing Then pictureBox.Image = image.ToBitmap() End If ' Retrieve Automobile objects. Dim carList As New List(Of Automobile) Dim resName As String = "EarlyAuto" Dim auto As Automobile Dim ctr As Integer = 1 Do auto = CType(resxSet.GetObject(resName + ctr.ToString()), Automobile) ctr += 1 If auto IsNot Nothing Then carList.Add(auto) Loop While auto IsNot Nothing cars = carList.ToArray() grid.DataSource = cars End Using End SubEnd Class

Convert .resx files to binary .resources files

Converting .resx files to embedded binary resource (.resources) files has significant advantages. Although .resx files are easy to read and maintain during application development, they are rarely included with finished applications. If they are distributed with an application, they exist as separate files apart from the application executable and its accompanying libraries. In contrast, .resources files are embedded in the application executable or its accompanying assemblies. In addition, for localized applications, relying on .resx files at run time places the responsibility for handling resource fallback on the developer. In contrast, if a set of satellite assemblies that contain embedded .resources files has been created, the common language runtime handles the resource fallback process.

To convert a .resx file to a .resources file, you use Resource File Generator (resgen.exe), which has the following basic syntax:

 resgen.exe .resxFilename

The result is a binary resource file that has the same root file name as the .resx file and a .resources file extension. This file can then be compiled into an executable or a library at compile time. If you are using the Visual Basic compiler, use the following syntax to embed a .resources file in an application's executable:

vbc filename .vb -resource: .resourcesFilename

If you are using C#, the syntax is as follows:

 csc filename .cs -resource: .resourcesFilename

The .resources file can also be embedded in a satellite assembly by using Assembly Linker (al.exe), which has the following basic syntax:

al resourcesFilename -out: assemblyFilename

See also

  • Create resource files
  • Resource File Generator (resgen.exe))
  • Assembly Linker (al.exe)
Top Articles
Latest Posts
Article information

Author: Aracelis Kilback

Last Updated: 04/23/2023

Views: 6013

Rating: 4.3 / 5 (64 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Aracelis Kilback

Birthday: 1994-11-22

Address: Apt. 895 30151 Green Plain, Lake Mariela, RI 98141

Phone: +5992291857476

Job: Legal Officer

Hobby: LARPing, role-playing games, Slacklining, Reading, Inline skating, Brazilian jiu-jitsu, Dance

Introduction: My name is Aracelis Kilback, I am a nice, gentle, agreeable, joyous, attractive, combative, gifted person who loves writing and wants to share my knowledge and understanding with you.