プログラムによる .resx ファイルの使用Working with .resx Files Programmatically

XML リソース (.resx) ファイルは適切に定義された XML で構成する必要があり、特定のスキーマに従ったヘッダーの後に、名前と値のペアになったデータが続きます。そのため、手動で作成するとエラーが発生しやすくなります。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. 代わりに、.NET Framework クラス ライブラリの型とメンバーを使って、.resx ファイルをプログラムで作成できます。As an alternative, you can create .resx files programmatically by using types and members in the .NET Framework Class Library. また、.resx ファイルに格納されているリソースを取得するために、.NET Framework クラス ライブラリを使うこともできます。You can also use the .NET Framework Class Library to retrieve resources that are stored in .resx files. このトピックでは、 System.Resources 名前空間の型とメンバーを使って、.resx ファイルを操作する方法を説明します。This topic explains how you can use the types and members in the System.Resources namespace to work with .resx files.

なお、この記事では、リソースを含む XML (.resx) ファイルの操作について説明します。Note that this article discusses working with XML (.resx) files that contain resources. アセンブリに埋め込まれたバイナリ リソース ファイルの操作について詳しくは、 ResourceManager トピックをご覧ください。For information on working with binary resource files that have been embedded in assemblies, see the ResourceManager topic.

警告

プログラムでの操作以外にも、.resx ファイルを操作する方法はあります。There are also ways to work with .resx files other than programmatically. リソース ファイルを Visual Studio プロジェクトに追加すると、Visual Studio では、.resx ファイルを作成して維持するためのインターフェイスが提供され、コンパイル時に .resx ファイルは .resources ファイルに自動的に変換されます。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. .resx ファイルを直接操作するためにテキスト エディターを使うこともできます。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.

.resx ファイルを作成するCreating a .resx File

System.Resources.ResXResourceWriter クラスを使い、次の手順に従って .resx ファイルをプログラムで作成できます。You can use the System.Resources.ResXResourceWriter class to create a .resx file programmatically, by following these steps:

  1. ResXResourceWriter メソッドを呼び出して、.resx ファイルの名前を指定することにより、 ResXResourceWriter.ResXResourceWriter(String) オブジェクトをインスタンス化します。Instantiate a ResXResourceWriter object by calling the ResXResourceWriter.ResXResourceWriter(String) method and supplying the name of the .resx file. ファイル名には、.resx 拡張子を含める必要があります。The file name must include the .resx extension. ResXResourceWriter ブロック内の using オブジェクトをインスタンス化する場合、手順 3 で ResXResourceWriter.Close メソッドを明示的に呼び出す必要はありません。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. ファイルに追加するリソースごとに ResXResourceWriter.AddResource メソッドを呼び出します。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. ResXResourceWriter.Close メソッドを呼び出して、リソース ファイルを生成し、すべてのリソースを解放します。Call the ResXResourceWriter.Close method to generate the resource file and to release all resources. ResXResourceWriter オブジェクトが using ブロック内で作成された場合、リソースは .resx ファイルに書き込まれ、 ResXResourceWriter オブジェクトが使うリソースは using ブロックの最後に解放されます。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.

結果として得られる .resx ファイルには、適切なヘッダーと data メソッドによって追加された各リソースの ResXResourceWriter.AddResource タグが含まれます。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.

次の例では、6 つの文字列、1 つのアイコン、2 つのアプリケーション定義オブジェクト (2 つの Automobile オブジェクト) を格納する CarResources.resx という名前の .resx ファイルを作成します。The following example creates a .resx file named CarResources.resx that stores six strings, an icon, and two application-defined objects (two Automobile objects). 例で定義されてインスタンス化された Automobile クラスは、 SerializableAttribute 属性でタグ付けされることに注意してください。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);  
      }
   }
}
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 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 Sub
End Module

重要

Visual Studio を使って .resx ファイルを作成することもできます。You can also use Visual Studio to create .resx files. コンパイル時に、Visual Studio は リソース ファイル ジェネレーター (Resgen.exe) を使って、.resx ファイルをバイナリ リソース (.resources) ファイルに変換し、アプリケーション アセンブリかサテライト アセンブリのいずれかに埋め込みます。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.

.resx ファイルをランタイムの実行可能ファイルに埋め込むことや、サテライト アセンブリにコンパイルすることはできません。You cannot embed a .resx file in a runtime executable or compile it into a satellite assembly. リソース ファイル ジェネレーター (Resgen.exe)を使って、.resx ファイルをバイナリ リソース (.resources) ファイルに変換する必要があります。You must convert your .resx file into a binary resource (.resources) file by using the Resource File Generator (Resgen.exe). 結果として得られる .resources ファイルは、アプリケーション アセンブリやサテライト アセンブリに埋め込むことができます。The resulting .resources file can then be embedded in an application assembly or a satellite assembly. 詳細については、「 Creating Resource Files」を参照してください。For more information, see Creating Resource Files.

リソースを列挙するEnumerating Resources

場合によっては、.resx ファイルから、特定のリソースではなく、すべてのリソースを取得したいことがあります。In some cases, you may want to retrieve all resources, instead of a specific resource, from a .resx file. これを行うには、.resx ファイル内のすべてのリソースの列挙子を提供する System.Resources.ResXResourceReader クラスを使います。To do this, you can use the System.Resources.ResXResourceReader class, which provides an enumerator for all resources in the .resx file. System.Resources.ResXResourceReader クラスは IDictionaryEnumeratorを実装します。これは、ループの反復処理ごとに特定のリソースを示す DictionaryEntry を返します。The System.Resources.ResXResourceReader class implements IDictionaryEnumerator, which returns a DictionaryEntry object that represents a particular resource for each iteration of the loop. その DictionaryEntry.Key プロパティはリソースのキーを返し、その DictionaryEntry.Value プロパティはリソースの値を返します。Its DictionaryEntry.Key property returns the resource's key, and its DictionaryEntry.Value property returns the resource's value.

次の例では、前の例で作成した CarResources.resx ファイルの ResXResourceReader オブジェクトを作成して、リソース ファイルを反復処理します。The following example creates a ResXResourceReader object for the CarResources.resx file created in the previous example and iterates through the resource file. リソース ファイルに定義された 2 つの Automobile オブジェクトを System.Collections.Generic.List<T> オブジェクトに追加し、6 個中 5 個の文字列を SortedList オブジェクトに追加します。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. SortedList オブジェクト内の値は、コンソールに列見出しを表示するために使われるパラメーター配列に変換されます。The values in the SortedList object are converted to a parameter array, which is used to display column headings to the console. Automobile プロパティ値もコンソールに表示されます。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.Collections
Imports System.Collections.Generic
Imports System.Resources

Module 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 Sub
End Module
' The example displays the following output:
'       Make     Model      Year   Doors   Cylinders
'       
'       Ford     Model N    1906       0           4
'       Ford     Model T    1909       2           4

特定のリソースを取得するRetrieving a Specific Resource

.resx ファイル内の項目を列挙することに加えて、 System.Resources.ResXResourceSet クラスを使って特定のリソースを名前によって取得できます。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. ResourceSet.GetString(String) メソッドは、名前付きの文字列リソースの値を取得します。The ResourceSet.GetString(String) method retrieves the value of a named string resource. ResourceSet.GetObject(String) メソッドは、名前付きオブジェクトの値やバイナリ データを取得します。The ResourceSet.GetObject(String) method retrieves the value of a named object or binary data. メソッドはオブジェクトを返します。そのオブジェクトはその後適切な型のオブジェクトにキャスト (C#) するか、変換 (Visual Basic) する必要があります。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. また、前の例で使ったアプリケーション定義の Automobile オブジェクトを取得して、 DataGridView コントロールに表示します。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.Generic
Imports System.Drawing
Imports System.Resources
Imports System.Windows.Forms

Public 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 Sub
End Class

.resx ファイルをバイナリ .resources ファイルに変換するConverting .resx Files to Binary .resources Files

.resx ファイルを埋め込みバイナリ リソース (.resources) ファイルに変換することには、大きな利点があります。Converting .resx files to embedded binary resource (.resources) files has significant advantages. .resx ファイルは、アプリケーション開発中の読み取りや保守を容易に行うことができますが、完成したアプリケーションに含まれることはほとんどありません。Although .resx files are easy to read and maintain during application development, they are rarely included with finished applications. .resx ファイルがアプリケーションと共に配布される場合、アプリケーションの実行可能ファイルとそれに付随するライブラリとは異なる独立したファイルとして存在します。If they are distributed with an application, they exist as separate files apart from the application executable and its accompanying libraries. これに対し、.resources ファイルは、アプリケーションの実行可能ファイルやそれに付随するアセンブリに埋め込まれます。In contrast, .resources files are embedded in the application executable or its accompanying assemblies. また、ローカライズされたアプリケーションの場合、実行時に .resx ファイルに依存すると、開発者がリソース フォールバックを処理することになります。In addition, for localized applications, relying on .resx files at run time places the responsibility for handling resource fallback on the developer. これに対し、埋め込みの .resources ファイルを含むサテライト アセンブリのセットが作成された場合、共通言語ランタイムがリソース フォールバック プロセスを処理します。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.

.resx ファイルを .resources ファイルに変換するには、 リソース ファイル ジェネレーター (Resgen.exe)を使います。リソース ファイル ジェネレーターの基本的な構文は次のとおりです。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 .resxFilenameResgen.exe .resxFilename

結果は、.resx ファイルと同じルート ファイル名と .resources ファイル拡張子を持つバイナリ リソース ファイルになります。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. Visual Basic コンパイラを使っている場合、次の構文を使って、.resources ファイルをアプリケーションの実行可能ファイルに埋め込みます。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: .resourcesFilenamevbc filename .vb -resource: .resourcesFilename

C# を使っている場合、構文は次のとおりです。If you are using C#, the syntax is as follows:

csc filename .cs /resource: .resourcesFilenamecsc filename .cs -resource: .resourcesFilename

アセンブリ リンカー (AL.exe)を使って、.resources ファイルをサテライト アセンブリに埋め込むこともできます。アセンブリ リンカーの基本的な構文は次のとおりです。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: assemblyFilenameal resourcesFilename -out: assemblyFilename

参照See Also

リソース ファイルの作成Creating Resource Files
Resgen.exe (リソース ファイル ジェネレーター)Resgen.exe (Resource File Generator)
Al.exe (アセンブリ リンカー)Al.exe (Assembly Linker)