프로그래밍 방식으로 .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 클래스 라이브러리의 형식 및 멤버를 사용하여 프로그래밍 방식으로 .resx 파일을 만들 수 있습니다.As an alternative, you can create .resx files programmatically by using types and members in the .NET Class Library. .NET 클래스 라이브러리를 사용하여 .resx 파일에 저장된 리소스를 가져올 수도 있습니다.You can also use the .NET 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 파일 만들기Create 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. 리소스가 개체이면 serialize 가능해야 합니다.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개, 아이콘 한 개 및 애플리케이션 정의 개체 2개( Automobile 개체 2개)를 저장하는 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.

리소스 열거Enumerate 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. 이 예제에서는 리소스 파일에 정의된 두 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

특정 리소스 가져오기Retrieve 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 파일로 변환Convert .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