1 out of 3 rated this helpful - Rate this topic

Working with .resx Files Programmatically

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 Framework Class Library. You can also use the .NET Framework Class Library to retrieve resources that are stored in .resx files. This topic explains how you can use the types and members in the System.Resources namespace to work with .resx files.

Caution noteCaution

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.

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.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.

Caution noteCaution

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). Note that 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);  
      }
   }
}


Important noteImportant

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 Creating Resource Files.

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


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;
      }
   }
}


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 the 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

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.