Share via


System.Resources.ResourceManager 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

Important

신뢰할 수 없는 데이터로 이 클래스에서 메서드를 호출하는 것은 보안상 위험합니다. 신뢰할 수 있는 데이터로만 이 클래스에서 메서드를 호출하세요. 자세한 내용은 모든 입력 유효성 검사를 참조 하세요.

클래스는 ResourceManager 어셈블리에 포함된 이진 .resources 파일 또는 독립 실행형 .resources 파일에서 리소스를 검색합니다. 앱이 지역화되고 지역화된 리소스가 위성 어셈블리배포된 경우 문화권별 리소스를 조회하고, 지역화된 리소스가 없을 때 리소스 대체를 제공하고, 리소스 직렬화를 지원합니다.

데스크톱 앱

데스크톱 앱의 경우 클래스는 ResourceManager 이진 리소스(.resources) 파일에서 리소스를 검색합니다. 일반적으로 언어 컴파일러 또는 AL.exe(어셈블리 링커) 는 이러한 리소스 파일을 어셈블리에 포함합니다. 개체를 사용하여 메서드를 ResourceManager 호출 CreateFileBasedResourceManager 하여 어셈블리에 포함되지 않은 .resources 파일에서 직접 리소스를 검색할 수도 있습니다.

주의

ASP.NET 앱에서 독립 실행형 .resources 파일을 사용하면 리소스가 메서드에서 명시적으로 해제 ReleaseAllResources 될 때까지 다시 잠기기 때문에 XCOPY 배포가 중단됩니다기본. ASP.NET 앱을 사용하여 리소스를 배포하려면 .resources 파일을 위성 어셈블리로 컴파일해야 합니다.

리소스 기반 앱에서 하나의 .resources 파일에는 문화권별 리소스를 찾을 수 없는 경우 리소스가 사용되는 기본 문화권의 리소스가 포함됩니다. 예를 들어 앱의 기본 문화권이 영어(en)인 경우 영어(미국) 또는 프랑스어(프랑스)(fr-FR)와 같은 특정 문화권에 대해 지역화된 리소스를 찾을 수 없을 때마다 영어 리소스가 사용됩니다. 일반적으로 기본 문화권의 리소스는 기본 앱 어셈블리에 포함되며 다른 지역화된 문화권에 대한 리소스는 위성 어셈블리에 포함됩니다. 위성 어셈블리에는 리소스만 포함됩니다. 루트 파일 이름은 기본 어셈블리와 동일하며 확장명은 .resources.dll. 어셈블리가 전역 어셈블리 캐시에 등록되지 않은 앱의 경우 위성 어셈블리는 어셈블리의 문화권에 해당하는 이름의 앱 하위 디렉터리에 저장됩니다.

리소스 만들기

리소스 기반 앱을 개발할 때는 텍스트 파일(.txt 또는 .restext 확장명이 있는 파일) 또는 XML 파일(확장명이 .resx인 파일)에 리소스 정보를 저장합니다. 그런 다음 Resgen.exe(리소스 파일 생성기)를 사용하여 텍스트 또는 XML 파일을 컴파일하여 이진 .resources 파일을 만듭니다. 그런 다음 C# 및 Visual Basic 컴파일러와 같은 /resources 컴파일러 옵션을 사용하여 결과 .resources 파일을 실행 파일 또는 라이브러리에 포함하거나 어셈블리 링커(AI.exe)를 사용하여 위성 어셈블리에 포함할 수 있습니다. Visual Studio 프로젝트에 .resx 파일을 포함하는 경우 Visual Studio는 빌드 프로세스의 일부로 기본 및 지역화된 리소스의 컴파일 및 포함을 자동으로 처리합니다.

이상적으로는 앱이 지원하는 모든 언어 또는 적어도 각 언어의 의미 있는 하위 집합에 대한 리소스를 만들어야 합니다. 이진 .resources 파일 이름은 명명 규칙 기본 이름을 따릅니다.cultureName.resources. 여기서 basename 은 원하는 세부 수준에 따라 앱의 이름 또는 클래스의 이름입니다. 속성 CultureInfo.Name 은 cultureName을 확인하는 데 사용됩니다. 앱의 기본 문화권에 대한 리소스의 이름은 basename.resources여야 합니다.

예를 들어 어셈블리에 기본 이름 MyResources가 있는 리소스 파일에 여러 리소스가 있다고 가정합니다. 이러한 리소스 파일에는 일본 문화권의 MyResources.ja-JP.resources, 독일 문화권의 MyResources.de.resources, 간소화된 중국 문화권의 경우 MyResources.zh-CHS.resources, 프랑스어(벨기에) 문화권의 MyResources.fr-BE.resources와 같은 이름이 있어야 합니다. 기본 리소스 파일의 이름은 MyResources.resources여야 합니다. 문화권별 리소스 파일은 일반적으로 각 문화권에 대한 위성 어셈블리에 패키지됩니다. 기본 리소스 파일은 앱의 기본 어셈블리에 포함되어야 합니다.

어셈블리 링커는 리소스를 프라이빗으로 표시할 수 있지만 다른 어셈블리에서 액세스할 수 있도록 항상 공용으로 표시해야 합니다. 위성 어셈블리에 코드가 없기 때문에 프라이빗으로 표시된 리소스는 어떤 메커니즘을 통해든 앱에서 사용할 수 없습니다.

리소스 만들기, 패키징 및 배포에 대한 자세한 내용은 리소스 파일 만들기, 위성 어셈블리 만들기, 리소스 패키징 및 배포 문서를 참조하세요.

ResourceManager 개체 인스턴스화

포함된 .resources 파일에서 해당 클래스 생성자 오버로드 중 하나를 호출하여 리소스를 검색하는 개체를 인스턴스화 ResourceManager 합니다. 이렇게 하면 개체를 ResourceManager 특정 .resources 파일 및 위성 어셈블리의 연결된 지역화된 .resources 파일과 긴밀하게 결합합니다.

가장 일반적으로 호출되는 두 생성자는 다음과 같습니다.

  • ResourceManager(String, Assembly) 는 .resources 파일의 기본 이름과 기본 .resources 파일이 있는 어셈블리의 두 가지 정보를 기반으로 리소스를 찾습니다. 기본 이름에는 문화권 또는 확장명 없이 .resources 파일의 네임스페이스 및 루트 이름이 포함됩니다. 명령줄에서 컴파일된 .resources 파일은 일반적으로 네임스페이스 이름을 포함하지 않는 반면 Visual Studio 환경에서 만든 .resources 파일은 포함되지 않습니다. 예를 들어 리소스 파일의 이름이 MyCompany.StringResources.resources이고 ResourceManager 생성자가 명명 Example.Main된 정적 메서드에서 호출되는 경우 다음 코드는 .resources 파일에서 리소스를 검색할 수 있는 개체를 인스턴스화 ResourceManager 합니다.

    ResourceManager rm = new ResourceManager("MyCompany.StringResources",
                                             typeof(Example).Assembly);
    
    Dim rm As New ResourceManager("MyCompany.StringResources",
                                GetType(Example2).Assembly)
    
  • ResourceManager(Type) 는 형식 개체의 정보를 기반으로 위성 어셈블리의 리소스를 조회합니다. 형식의 정규화된 이름은 파일 이름 확장명 없이 .resources 파일의 기본 이름에 해당합니다. Visual Studio 리소스 디자이너를 사용하여 만든 데스크톱 앱에서 Visual Studio는 정규화된 이름이 .resources 파일의 루트 이름과 동일한 래퍼 클래스를 만듭니다. 예를 들어 리소스 파일의 이름이 MyCompany.StringResources.resources이고 래퍼 클래스가 있는 MyCompany.StringResources경우 다음 코드는 .resources 파일에서 리소스를 검색할 수 있는 개체를 인스턴스화 ResourceManager 합니다.

    ResourceManager rm = new ResourceManager(typeof(MyCompany.StringResources));
    
    Dim rm As New ResourceManager(GetType(MyCompany.StringResources))
    

적절한 리소스를 찾을 수 없는 경우 생성자 호출은 유효한 ResourceManager 개체를 만듭니다. 그러나 리소스를 검색하려고 시도하면 예외가 MissingManifestResourceException throw됩니다. 예외 처리에 대한 자세한 내용은 이 문서의 뒷부분에 나오는 MissingManifestResourceException 및 MissingSatelliteAssemblyException 예외 처리 섹션을 참조하세요.

다음 예제에서는 개체를 인스턴스화하는 ResourceManager 방법을 보여줍니다. ShowTime.exe 실행 파일에 대한 소스 코드가 포함되어 있습니다. 또한 단일 문자열 리소스 TimeHeader를 포함하는 Strings.txt 다음과 같은 텍스트 파일을 포함합니다.

TimeHeader=The current time is

일괄 처리 파일을 사용하여 리소스 파일을 생성하고 실행 파일에 포함할 수 있습니다. 다음은 C# 컴파일러를 사용하여 실행 파일을 생성하는 일괄 처리 파일입니다.

resgen strings.txt
csc ShowTime.cs /resource:strings.resources

Visual Basic 컴파일러의 경우 다음 일괄 처리 파일을 사용할 수 있습니다.

resgen strings.txt
vbc ShowTime.vb /resource:strings.resources
using System;
using System.Resources;

public class ShowTimeEx
{
    public static void Main()
    {
        ResourceManager rm = new ResourceManager("Strings",
                                 typeof(Example).Assembly);
        string timeString = rm.GetString("TimeHeader");
        Console.WriteLine("{0} {1:T}", timeString, DateTime.Now);
    }
}
// The example displays output like the following:
//        The current time is 2:03:14 PM
Imports System.Resources

Module Example6
    Public Sub Main()
        Dim rm As New ResourceManager("Strings", GetType(Example6).Assembly)
        Dim timeString As String = rm.GetString("TimeHeader")
        Console.WriteLine("{0} {1:T}", timeString, Date.Now)
    End Sub
End Module
' The example displays output similar to the following:
'       The current time is 2:03:14 PM

ResourceManager 및 문화권별 리소스

지역화된 앱은 리소스 패키징 및 배포 문서에 설명된 대로 리소스를 배포해야 합니다. 어셈블리가 제대로 구성된 경우 리소스 관리자는 현재 스레드의 Thread.CurrentUICulture 속성을 기반으로 검색할 리소스를 결정합니다. (이 속성은 현재 스레드의 UI 문화권도 반환합니다.) 예를 들어 앱이 기본 어셈블리의 기본 영어 리소스와 두 위성 어셈블리의 프랑스어 및 러시아어 리소스로 컴파일되고 Thread.CurrentUICulture 속성이 fr-FR로 설정된 경우 리소스 관리자는 프랑스어 리소스를 검색합니다.

속성을 명시적으로 또는 암시적으로 설정할 CurrentUICulture 수 있습니다. 설정하는 방법은 개체가 ResourceManager 문화권에 따라 리소스를 검색하는 방법을 결정합니다.

  • 속성을 특정 문화권 Thread.CurrentUICulture 으로 명시적으로 설정하는 경우 리소스 관리자는 사용자의 브라우저 또는 운영 체제 언어에 관계없이 항상 해당 문화권에 대한 리소스를 검색합니다. 기본 영어 리소스와 영어(미국), 프랑스어(프랑스) 및 러시아어(러시아)에 대한 리소스가 포함된 3개의 위성 어셈블리로 컴파일된 앱을 고려합니다. CurrentUICulture 속성이 fr-FR ResourceManager 로 설정된 경우 개체는 사용자의 운영 체제 언어가 프랑스어가 아니더라도 항상 프랑스어(프랑스) 리소스를 검색합니다. 속성을 명시적으로 설정하기 전에 이 동작이 원하는 동작인지 확인합니다.

    ASP.NET 앱에서는 서버의 설정이 Thread.CurrentUICulture 들어오는 클라이언트 요청과 일치할 가능성이 낮기 때문에 속성을 명시적으로 설정해야 합니다. ASP.NET 앱은 Thread.CurrentUICulture 속성을 사용자의 브라우저 허용 언어로 명시적으로 설정할 수 있습니다.

    속성을 명시적으로 설정하면 Thread.CurrentUICulture 해당 스레드에 대한 현재 UI 문화권이 정의됩니다. 앱에 있는 다른 스레드의 현재 UI 문화권에는 영향을 주지 않습니다.

  • 해당 문화권을 나타내는 개체를 정적 CultureInfo.DefaultThreadCurrentUICulture 속성에 할당하여 CultureInfo 기본 앱의 모든 스레드에 대한 UI 문화권을 설정할 수 있습니다.

  • 현재 UI 문화권을 명시적으로 설정하지 않고 현재 앱에 대한 기본 문화권을 정의하지 않으면기본 CultureInfo.CurrentUICulture 속성은 Windows GetUserDefaultUILanguage 함수에 의해 암시적으로 설정됩니다. 이 함수는 사용자가 기본 언어를 설정할 수 있도록 하는 MUI(다국어 사용자 인터페이스)에서 제공됩니다. 사용자가 UI 언어를 설정하지 않은 경우 기본적으로 운영 체제 리소스의 언어인 시스템 설치 언어로 설정됩니다.

다음은 현재 UI 문화권을 명시적으로 설정하는 간단한 "Hello world" 예제입니다. 영어(미국) 또는 en-US, 프랑스어(프랑스) 또는 fr-FR, 러시아어(러시아) 또는 ru-RU의 세 가지 문화권에 대한 리소스를 포함합니다. en-US 리소스는 Greetings.txt이라는 텍스트 파일에 포함됩니다.

HelloString=Hello world!

fr-FR 리소스는 Greetings.fr-FR.txt 텍스트 파일에 포함됩니다.

HelloString=Salut tout le monde!

ru-RU 리소스는 Greetings.ru-RU.txt 텍스트 파일에 포함됩니다.

HelloString=Всем привет!

다음은 예제의 소스 코드입니다(C# 버전의 경우 Visual Basic 버전 또는 Example.cs Example.vb).

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

public class Example
{
    public static void Main()
    {
        // Create array of supported cultures
        string[] cultures = { "en-CA", "en-US", "fr-FR", "ru-RU" };
        Random rnd = new Random();
        int cultureNdx = rnd.Next(0, cultures.Length);
        CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;
        ResourceManager rm = new ResourceManager("Greetings", typeof(Example).Assembly);
        try
        {
            CultureInfo newCulture = new CultureInfo(cultures[cultureNdx]);
            Thread.CurrentThread.CurrentCulture = newCulture;
            Thread.CurrentThread.CurrentUICulture = newCulture;
            string greeting = String.Format("The current culture is {0}.\n{1}",
                                            Thread.CurrentThread.CurrentUICulture.Name,
                                            rm.GetString("HelloString"));
            Console.WriteLine(greeting);
        }
        catch (CultureNotFoundException e)
        {
            Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName);
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = originalCulture;
            Thread.CurrentThread.CurrentUICulture = originalCulture;
        }
    }
}
// The example displays output like the following:
//       The current culture is ru-RU.
//       Всем привет!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

Module Example
   Sub Main()
      ' Create array of supported cultures
      Dim cultures() As String = {"en-CA", "en-US", "fr-FR", "ru-RU" }
      Dim rnd As New Random()
      Dim cultureNdx As Integer = rnd.Next(0, cultures.Length)
      Dim originalCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
      Dim rm As New ResourceManager("Greetings", GetType(Example).Assembly)
      Try
         Dim newCulture As New CultureInfo(cultures(cultureNdx))
         Thread.CurrentThread.CurrentCulture = newCulture
         Thread.CurrentThread.CurrentUICulture = newCulture
         Dim greeting As String = String.Format("The current culture is {0}.{1}{2}",
                                                Thread.CurrentThread.CurrentUICulture.Name,
                                                vbCrLf, rm.GetString("HelloString"))

         Console.WriteLine(greeting)
      Catch e As CultureNotFoundException
         Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName)
      Finally
         Thread.CurrentThread.CurrentCulture = originalCulture
         Thread.CurrentThread.CurrentUICulture = originalCulture
      End Try
   End Sub
End Module
' The example displays output like the following:
'       The current culture is ru-RU.
'       Всем привет!

이 예제를 컴파일하려면 다음 명령이 포함된 일괄 처리(.bat) 파일을 만들고 명령 프롬프트에서 실행합니다. C# cscvbcExample.csExample.vb을 사용하는 경우 대신 지정합니다.

resgen Greetings.txt
vbc Example.vb /resource:Greetings.resources

resgen Greetings.fr-FR.txt
Md fr-FR
al /embed:Greetings.fr-FR.resources /culture:fr-FR /out:fr-FR\Example.resources.dll

resgen Greetings.ru-RU.txt
Md ru-RU
al /embed:Greetings.ru-RU.resources /culture:ru-RU /out:ru-RU\Example.resources.dll

리소스 검색

특정 리소스에 GetObject(String) 액세스하기 위해 메서드 및 GetString(String) 메서드를 호출합니다. 메서드를 호출하여 문자열이 GetStream(String) 아닌 리소스를 바이트 배열로 검색할 수도 있습니다. 기본적으로 지역화된 리소스가 있는 앱에서 이러한 메서드는 호출을 수행한 스레드의 현재 UI 문화권에 의해 결정되는 문화권에 대한 리소스를 반환합니다. 스레드의 현재 UI 문화권이 정의되는 방법에 대한 자세한 내용은 이전 섹션인 ResourceManager 및 문화권별 리소스를 참조하세요. 리소스 관리자가 현재 스레드의 UI 문화권에 대한 리소스를 찾을 수 없는 경우 대체 프로세스를 사용하여 지정된 리소스를 검색합니다. 리소스 관리자가 지역화된 리소스를 찾을 수 없는 경우 기본 문화권의 리소스를 사용합니다. 리소스 대체 규칙에 대한 자세한 내용은 리소스 패키징 및 배포 문서의 "리소스 대체 프로세스" 섹션을 참조하세요.

참고 항목

클래스 생성자에 지정된 ResourceManager .resources 파일을 찾을 수 없는 경우 리소스를 검색하려고 하면 예외가 MissingManifestResourceExceptionMissingSatelliteAssemblyException throw됩니다. 예외 처리에 대한 자세한 내용은 이 문서의 뒷부분에 나오는 MissingManifestResourceException 및 MissingSatelliteAssemblyException 예외 처리 섹션을 참조하세요.

다음 예제에서는 메서드를 GetString 사용하여 문화권별 리소스를 검색합니다. 영어(en), 프랑스어(프랑스)(fr-FR) 및 러시아어(러시아)(ru-RU) 문화권에 대한 .txt 파일에서 컴파일된 리소스로 구성됩니다. 이 예제에서는 현재 문화권과 현재 UI 문화권을 영어(미국), 프랑스어(프랑스), 러시아어(러시아) 및 스웨덴어(스웨덴)로 변경합니다. 그런 다음 메서드를 GetString 호출하여 지역화된 문자열을 검색합니다. 이 문자열은 현재 날짜 및 월과 함께 표시됩니다. 현재 UI 문화권이 스웨덴어(스웨덴)인 경우를 제외하고 출력에 적절한 지역화된 문자열이 표시됩니다. 스웨덴어 언어 리소스를 사용할 수 없으므로 앱은 대신 영어인 기본 문화권의 리소스를 사용합니다.

이 예제에서는 다음 표에 나열된 텍스트 기반 리소스 파일이 필요합니다. 각각에는 이름이 DateStart1개인 문자열 리소스가 있습니다.

문화권 File name 리소스 이름 리소스 값
en-US DateStrings.txt DateStart 현재는 다음과 입니다.
fr-FR DateStrings.fr-FR.txt DateStart 오주르드후이, c'est le
ru-RU DateStrings.ru-RU.txt DateStart Сегодня

다음은 예제의 소스 코드입니다(Visual Basic 버전에 대한 ShowDate.vb 또는 코드의 C# 버전에 대한 ShowDate.cs).

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en")]

public class ShowDateEx
{
    public static void Main()
    {
        string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "sv-SE" };
        ResourceManager rm = new ResourceManager("DateStrings",
                                                 typeof(Example).Assembly);

        foreach (var cultureName in cultureNames)
        {
            CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;

            Console.WriteLine("Current UI Culture: {0}",
                              CultureInfo.CurrentUICulture.Name);
            string dateString = rm.GetString("DateStart");
            Console.WriteLine("{0} {1:M}.\n", dateString, DateTime.Now);
        }
    }
}
// The example displays output similar to the following:
//       Current UI Culture: en-US
//       Today is February 03.
//       
//       Current UI Culture: fr-FR
//       Aujourd'hui, c'est le 3 février
//       
//       Current UI Culture: ru-RU
//       Сегодня февраля 03.
//       
//       Current UI Culture: sv-SE
//       Today is den 3 februari.
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly:NeutralResourcesLanguage("en")>

Module Example5
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "sv-SE"}
        Dim rm As New ResourceManager("DateStrings",
                                    GetType(Example5).Assembly)

        For Each cultureName In cultureNames
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current UI Culture: {0}",
                           CultureInfo.CurrentUICulture.Name)
            Dim dateString As String = rm.GetString("DateStart")
            Console.WriteLine("{0} {1:M}.", dateString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'       Current UI Culture: en-US
'       Today is February 03.
'       
'       Current UI Culture: fr-FR
'       Aujourd'hui, c'est le 3 février
'       
'       Current UI Culture: ru-RU
'       Сегодня февраля 03.
'       
'       Current UI Culture: sv-SE
'       Today is den 3 februari.

이 예제를 컴파일하려면 다음 명령이 포함된 일괄 처리 파일을 만들고 명령 프롬프트에서 실행합니다. C# cscvbcshowdate.csshowdate.vb을 사용하는 경우 대신 지정합니다.

resgen DateStrings.txt
vbc showdate.vb /resource:DateStrings.resources

md fr-FR
resgen DateStrings.fr-FR.txt
al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources

md ru-RU
resgen DateStrings.ru-RU.txt
al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources

현재 UI 문화권 이외의 특정 문화권의 리소스를 검색하는 방법에는 두 가지가 있습니다.

  • 또는 GetObject(String, CultureInfo)GetStream(String, CultureInfo) 메서드를 GetString(String, CultureInfo)호출하여 특정 문화권에 대한 리소스를 검색할 수 있습니다. 지역화된 리소스를 찾을 수 없는 경우 리소스 관리자는 리소스 대체 프로세스를 사용하여 적절한 리소스를 찾습니다.
  • 메서드를 GetResourceSet 호출하여 특정 문화권의 ResourceSet 리소스를 나타내는 개체를 가져올 수 있습니다. 메서드 호출에서 리소스 관리자가 지역화된 리소스를 찾을 수 없는 경우 부모 문화권에 대해 검색하는지 또는 단순히 기본 문화권의 리소스로 되돌아가는지 여부를 확인할 수 있습니다. 그런 다음 메서드를 ResourceSet 사용하여 이름으로 리소스(해당 문화권에 대해 지역화됨)에 액세스하거나 집합의 리소스를 열거할 수 있습니다.

MissingManifestResourceException 및 MissingSatelliteAssemblyException 예외 처리

특정 리소스를 검색하려고 하지만 리소스 관리자가 해당 리소스를 찾을 수 없고 기본 문화권이 정의되지 않았거나 기본 문화권의 리소스를 찾을 수 없는 경우 리소스 관리자는 기본 어셈블리에서 리소스를 찾거나 MissingSatelliteAssemblyException 위성 어셈블리에서 리소스를 찾을 것으로 예상되는 경우 예외를 throw MissingManifestResourceException 합니다. 개체를 인스턴스화할 때가 아니라 리소스 검색 메서드를 GetString 호출할 GetObject때 예외가 ResourceManager throw됩니다.

예외는 일반적으로 다음 조건에서 throw됩니다.

  • 적절한 리소스 파일 또는 위성 어셈블리가 없습니다. 리소스 관리자가 앱의 기본 리소스가 기본 앱 어셈블리에 포함될 것으로 예상하는 경우 해당 리소스가 없습니다. 특성이 NeutralResourcesLanguageAttribute 앱의 기본 리소스가 위성 어셈블리에 있음을 나타내는 경우 해당 어셈블리를 찾을 수 없습니다. 앱을 컴파일할 때 리소스가 기본 어셈블리에 포함되어 있는지 또는 필요한 위성 어셈블리가 생성되고 적절하게 이름이 지정되었는지 확인합니다. 해당 이름은 appName.resources.dll 형식을 사용해야 하며, 리소스가 포함된 문화권의 이름을 따서 명명된 디렉터리에 있어야 합니다.

  • 앱에 기본 또는 중립 문화권이 정의되지 않았습니다. NeutralResourcesLanguageAttribute 소스 코드 파일 또는 프로젝트 정보 파일(Visual Basic 앱의 경우 AssemblyInfo.vb 또는 C# 앱의 AssemblyInfo.cs) 파일에 특성을 추가합니다.

  • 생성자의 매개 변수 ResourceManager(String, Assembly)baseName .resources 파일의 이름을 지정하지 않습니다. 이름에는 리소스 파일의 정규화된 네임스페이스가 포함되어야 하지만 파일 이름 확장명은 포함하지 않아야 합니다. 일반적으로 Visual Studio에서 만든 리소스 파일에는 네임스페이스 이름이 포함되지만 명령 프롬프트에서 생성되고 컴파일된 리소스 파일은 포함되지 않습니다. 다음 유틸리티를 컴파일하고 실행하여 포함된 .resources 파일의 이름을 확인할 수 있습니다. 기본 어셈블리 또는 위성 어셈블리의 이름을 명령줄 매개 변수로 허용하는 콘솔 앱입니다. 리소스 관리자가 리소스를 올바르게 식별할 수 있도록 매개 변수로 baseName 제공해야 하는 문자열을 표시합니다.

    using System;
    using System.IO;
    using System.Reflection;
    
    public class Example0
    {
       public static void Main()
       {
          if (Environment.GetCommandLineArgs().Length == 1) { 
             Console.WriteLine("No filename.");
             return;
          }
          
          string filename = Environment.GetCommandLineArgs()[1].Trim();
          // Check whether the file exists.
          if (! File.Exists(filename)) {
             Console.WriteLine("{0} does not exist.", filename);
             return;
          }   
          
          // Try to load the assembly.
          Assembly assem = Assembly.LoadFrom(filename);
          Console.WriteLine("File: {0}", filename);
             
          // Enumerate the resource files.
          string[] resNames = assem.GetManifestResourceNames();
          if (resNames.Length == 0)
             Console.WriteLine("   No resources found.");
    
          foreach (var resName in resNames)
             Console.WriteLine("   Resource: {0}", resName.Replace(".resources", ""));
    
          Console.WriteLine();
       }
    }
    
    Imports System.IO
    Imports System.Reflection
    Imports System.Resources
    
    Module Example
       Public Sub Main()
          If Environment.GetCommandLineArgs.Length = 1 Then 
             Console.WriteLine("No filename.")
             Exit Sub
          End If
          Dim filename As String = Environment.GetCommandLineArgs(1).Trim()
          ' Check whether the file exists.
          If Not File.Exists(filename) Then
             Console.WriteLine("{0} does not exist.", filename)
             Exit Sub
          End If   
          
          ' Try to load the assembly.
          Dim assem As Assembly = Assembly.LoadFrom(filename)
          Console.WriteLine("File: {0}", filename)
             
          ' Enumerate the resource files.
          Dim resNames() As String = assem.GetManifestResourceNames()
          If resNames.Length = 0 Then
             Console.WriteLine("   No resources found.")
          End If
          For Each resName In resNames
             Console.WriteLine("   Resource: {0}", resName.Replace(".resources", ""))
          Next
          Console.WriteLine()
       End Sub
    End Module
    

애플리케이션의 현재 문화권을 명시적으로 변경하는 경우 리소스 관리자는 속성이 아닌 CultureInfo.CurrentCulture 속성 값에 따라 리소스 집합을 CultureInfo.CurrentUICulture 검색한다는 점을 기억해야 합니다. 일반적으로 한 값을 변경하는 경우 다른 값도 변경해야 합니다.

리소스 버전 관리

앱의 기본 리소스를 포함하는 기본 어셈블리는 앱의 위성 어셈블리와 별개이므로 위성 어셈블리를 다시 배포하지 않고도 새 버전의 기본 어셈블리를 릴리스할 수 있습니다. 특성을 사용하여 SatelliteContractVersionAttribute 기존 위성 어셈블리를 사용하고 리소스 관리자에게 새 버전의 기본 어셈블리로 다시 배포하지 않도록 지시합니다.

위성 어셈블리에 대한 버전 관리 지원에 대한 자세한 내용은 리소스 검색 문서를 참조하세요.

<satelliteassemblies> 구성 파일 노드

참고 항목

이 섹션은 .NET Framework 앱과 관련이 있습니다.

웹 사이트(HREF .exe 파일) ResourceManager 에서 배포되고 실행되는 실행 파일의 경우 개체는 웹을 통해 위성 어셈블리를 검색하여 앱의 성능을 저하할 수 있습니다. 성능 문제를 제거하기 위해 이 검색을 앱과 함께 배포한 위성 어셈블리로 제한할 수 있습니다. 이렇게 하려면 앱의 구성 파일에 노드를 <satelliteassemblies> 만들어 앱에 대한 특정 문화권 집합을 배포했으며 개체가 해당 ResourceManager 노드에 나열되지 않은 문화권을 검색하지 않도록 지정합니다.

참고 항목

노드를 만드는 <satelliteassemblies> 기본 대안은 ClickOnce 배포 매니페스트 기능을 사용하는 것입니다.

앱의 구성 파일에서 다음과 유사한 섹션을 만듭니다.

<?xml version ="1.0"?>
<configuration>
  <satelliteassemblies>
    <assembly name="MainAssemblyName, Version=versionNumber, Culture=neutral, PublicKeyToken=null|yourPublicKeyToken">
      <culture>cultureName1</culture>
      <culture>cultureName2</culture>
      <culture>cultureName3</culture>
    </assembly>
  </satelliteassemblies>
</configuration>

다음과 같이 이 구성 정보를 편집합니다.

  • 배포하는 각 기본 어셈블리에 대해 하나 이상의 <assembly> 노드를 지정합니다. 여기서 각 노드는 정규화된 어셈블리 이름을 지정합니다. MainAssemblyName 대신 기본 어셈블리의 이름을 지정하고 기본 어셈블리에 해당하는 , PublicKeyTokenCulture 특성 값을 지정Version합니다.

    특성의 Version 경우 어셈블리의 버전 번호를 지정합니다. 예를 들어 어셈블리의 첫 번째 릴리스는 버전 번호 1.0.0.0일 수 있습니다.

    특성의 PublicKeyToken 경우 강력한 이름으로 어셈블리에 서명하지 않은 경우 키워드(keyword) null 지정하거나 어셈블리에 서명한 경우 공개 키 토큰을 지정합니다.

    특성의 Culture 경우 키워드(keyword) 지정하여 기본 neutral 어셈블리를 지정하고 클래스가 ResourceManager 노드에 <culture> 나열된 문화권에 대해서만 검색하도록 합니다.

    정규화된 어셈블리 이름에 대한 자세한 내용은 어셈블리 이름 문서를 참조하세요. 강력한 이름의 어셈블리에 대한 자세한 내용은 강력한 이름의 어셈블리 만들기 및 사용 문서를 참조하세요.

  • 특정 문화권 이름(예: "fr-FR") 또는 중립 문화권 이름(예: "fr")을 사용하여 하나 이상의 <culture> 노드를 지정합니다.

노드 ResourceManager 아래에 <satelliteassemblies> 나열되지 않은 어셈블리에 리소스가 필요한 경우 클래스는 표준 검색 규칙을 사용하여 문화권을 검색합니다.

Windows 8.x 앱

Important

클래스는 ResourceManager Windows 8.x 앱에서 지원되지만 사용하지 않는 것이 좋습니다. Windows 8.x 앱에서 사용할 수 있는 이식 가능한 클래스 라이브러리 프로젝트를 개발하는 경우에만 이 클래스를 사용합니다. Windows 8.x 앱에서 리소스를 검색하려면 Windows.ApplicationModel.Resources.ResourceLoader 클래스를 대신 사용합니다.

Windows 8.x 앱의 경우 클래스는 ResourceManager PRI(패키지 리소스 인덱스) 파일에서 리소스를 검색합니다. 단일 PRI 파일(애플리케이션 패키지 PRI 파일)에는 기본 문화권과 지역화된 문화권 모두에 대한 리소스가 포함됩니다. MakePRI 유틸리티를 사용하여 XML 리소스(.resw) 형식인 하나 이상의 리소스 파일에서 PRI 파일을 만듭니다. Visual Studio 프로젝트에 포함된 리소스의 경우 Visual Studio는 PRI 파일을 자동으로 만들고 패키징하는 프로세스를 처리합니다. 그런 다음 .NET ResourceManager 클래스를 사용하여 앱 또는 라이브러리의 리소스에 액세스할 수 있습니다.

데스크톱 앱과 ResourceManager 동일한 방식으로 Windows 8.x 앱에 대한 개체를 인스턴스화할 수 있습니다.

그런 다음 검색할 리소스의 이름을 메서드에 전달하여 특정 문화권의 리소스에 GetString(String) 액세스할 수 있습니다. 기본적으로 이 메서드는 호출한 스레드의 현재 UI 문화권에 의해 결정되는 문화권에 대한 리소스를 반환합니다. 리소스의 이름과 CultureInfo 해당 리소스를 메서드로 검색할 문화권을 나타내는 개체를 전달하여 특정 문화권에 대한 리소스를 GetString(String, CultureInfo) 검색할 수도 있습니다. 현재 UI 문화권 또는 지정된 문화권에 대한 리소스를 찾을 수 없는 경우 리소스 관리자는 UI 언어 대체 목록을 사용하여 적절한 리소스를 찾습니다.

예제

다음 예제에서는 명시적 문화권 및 암시적 현재 UI 문화권을 사용하여 기본 어셈블리 및 위성 어셈블리에서 문자열 리소스를 가져오는 방법을 보여 줍니다. 자세한 내용은 위성 어셈블리 만들기 항목의 "전역 어셈블리 캐시에 설치되지 않은 위성 어셈블리의 디렉터리 위치" 섹션을 참조하세요 .

이 예제를 실행하려면 다음을 수행합니다.

  1. 앱 디렉터리에서 다음 리소스 문자열을 포함하는 rmc.txt 파일을 만듭니다.

    day=Friday
    year=2006
    holiday="Cinco de Mayo"
    
  2. 리소스 파일 생성기를 사용하여 다음과 같이 rmc.txt 입력 파일에서 rmc.resources 리소스 파일을 생성합니다.

    resgen rmc.txt
    
  3. 앱 디렉터리의 하위 디렉터리를 만들고 이름을 "es-MX"로 지정합니다. 다음 세 단계에서 만들 위성 어셈블리의 문화권 이름입니다.

  4. 다음 리소스 문자열을 포함하는 es-MX 디렉터리에 rmc.es-MX.txt 파일을 만듭니다.

    day=Viernes
    year=2006
    holiday="Cinco de Mayo"
    
  5. 리소스 파일 생성기를 사용하여 다음과 같이 rmc.es-MX.txt 입력 파일에서 rmc.es-MX.resources 리소스 파일을 생성합니다.

    resgen rmc.es-MX.txt
    
  6. 이 예제의 파일 이름이 rmc.vb 또는 rmc.cs 가정합니다. 다음 소스 코드를 파일에 복사합니다. 그런 다음 컴파일하고 기본 어셈블리 리소스 파일인 rmc.resources를 실행 가능한 어셈블리에 포함합니다. Visual Basic 컴파일러를 사용하는 경우 구문은 다음과 같습니다.

    vbc rmc.vb /resource:rmc.resources
    

    C# 컴파일러에 해당하는 구문은 다음과 같습니다.

    csc /resource:rmc.resources rmc.cs
    
  7. 어셈블리 링커를 사용하여 위성 어셈블리를 만듭니다. 앱의 기본 이름이 rmc인 경우 위성 어셈블리 이름은 rmc.resources.dll 합니다. 위성 어셈블리는 es-MX 디렉터리에 만들어야 합니다. es-MX가 현재 디렉터리인 경우 다음 명령을 사용합니다.

    al /embed:rmc.es-MX.resources /c:es-MX /out:rmc.resources.dll
    
  8. rmc.exe 실행하여 포함된 리소스 문자열을 가져오고 표시합니다.

    using System;
    using System.Globalization;
    using System.Resources;
    
    class Example2
    {
        public static void Main()
        {
            string day;
            string year;
            string holiday;
            string celebrate = "{0} will occur on {1} in {2}.\n";
    
            // Create a resource manager.
            ResourceManager rm = new ResourceManager("rmc",
                                     typeof(Example).Assembly);
    
            Console.WriteLine("Obtain resources using the current UI culture.");
    
            // Get the resource strings for the day, year, and holiday
            // using the current UI culture.
            day = rm.GetString("day");
            year = rm.GetString("year");
            holiday = rm.GetString("holiday");
            Console.WriteLine(celebrate, holiday, day, year);
    
            // Obtain the es-MX culture.
            CultureInfo ci = new CultureInfo("es-MX");
    
            Console.WriteLine("Obtain resources using the es-MX culture.");
    
            // Get the resource strings for the day, year, and holiday
            // using the specified culture.
            day = rm.GetString("day", ci);
            year = rm.GetString("year", ci);
            holiday = rm.GetString("holiday", ci);
            // ---------------------------------------------------------------
            // Alternatively, comment the preceding 3 code statements and
            // uncomment the following 4 code statements:
            // ----------------------------------------------------------------
            // Set the current UI culture to "es-MX" (Spanish-Mexico).
            //    Thread.CurrentThread.CurrentUICulture = ci;
    
            // Get the resource strings for the day, year, and holiday
            // using the current UI culture. Use those strings to
            // display a message.
            //    day  = rm.GetString("day");
            //    year = rm.GetString("year");
            //    holiday = rm.GetString("holiday");
            // ---------------------------------------------------------------
    
            // Regardless of the alternative that you choose, display a message
            // using the retrieved resource strings.
            Console.WriteLine(celebrate, holiday, day, year);
        }
    }
    /*
    This example displays the following output:
    
       Obtain resources using the current UI culture.
       "5th of May" will occur on Friday in 2006.
    
       Obtain resources using the es-MX culture.
       "Cinco de Mayo" will occur on Viernes in 2006.
    */
    
    Imports System.Resources
    Imports System.Reflection
    Imports System.Threading
    Imports System.Globalization
    
    Class Example4
        Public Shared Sub Main()
            Dim day As String
            Dim year As String
            Dim holiday As String
            Dim celebrate As String = "{0} will occur on {1} in {2}." & vbCrLf
    
            ' Create a resource manager. 
            Dim rm As New ResourceManager("rmc", GetType(Example4).Assembly)
    
            Console.WriteLine("Obtain resources using the current UI culture.")
    
            ' Get the resource strings for the day, year, and holiday 
            ' using the current UI culture. 
            day = rm.GetString("day")
            year = rm.GetString("year")
            holiday = rm.GetString("holiday")
            Console.WriteLine(celebrate, holiday, day, year)
    
            ' Obtain the es-MX culture.
            Dim ci As New CultureInfo("es-MX")
    
            Console.WriteLine("Obtain resources using the es-MX culture.")
    
            ' Get the resource strings for the day, year, and holiday 
            ' using the es-MX culture.  
            day = rm.GetString("day", ci)
            year = rm.GetString("year", ci)
            holiday = rm.GetString("holiday", ci)
    
            ' ---------------------------------------------------------------
            ' Alternatively, comment the preceding 3 code statements and 
            ' uncomment the following 4 code statements:
            ' ----------------------------------------------------------------
            ' Set the current UI culture to "es-MX" (Spanish-Mexico).
            '    Thread.CurrentThread.CurrentUICulture = ci
            ' Get the resource strings for the day, year, and holiday 
            ' using the current UI culture. 
            '    day  = rm.GetString("day")
            '    year = rm.GetString("year")
            '    holiday = rm.GetString("holiday")
            ' ---------------------------------------------------------------
    
            ' Regardless of the alternative that you choose, display a message 
            ' using the retrieved resource strings.
            Console.WriteLine(celebrate, holiday, day, year)
        End Sub
    End Class
    ' This example displays the following output:
    'Obtain resources using the current UI culture.
    '"5th of May" will occur on Friday in 2006.
    '
    'Obtain resources using the es-MX culture.
    '"Cinco de Mayo" will occur on Viernes in 2006.