다음을 통해 공유


방법: 관리 권한 없이 사용자 지정 문화권 저장

업데이트: 2010년 12월

이 항목에서는 관리 권한이 없는 상태에서 파일에 사용자 지정 culture 데이터를 저장하는 방법에 대해 설명합니다. 관리 권한이 있는 상태로 실행 중인 응용 프로그램에서는 방법: 사용자 지정 Culture 만들기 항목에 설명된 대로 CultureAndRegionInfoBuilder.Register를 사용하여 사용자 지정 culture를 등록합니다. 내부적으로 이 메서드는 관리 권한이 필요하지 않은 CultureDefinition.Compile 메서드를 호출합니다.

리플렉션을 사용하여 CultureDefinition.Compile 메서드에 직접 액세스하면 관리 권한 없이도 사용자 지정 culture를 저장할 수 있습니다.

주의 정보주의

CultureDefinition.Compile 메서드를 직접 호출하는 것은 지원되지 않습니다.메서드는 예고 없이 변경 또는 제거될 수 있습니다.이 항목에서는 .NET Framework 버전 4의 동작에 대해서만 설명합니다.이 메서드를 잘못 사용하면 컴퓨터가 불안정한 상태가 되어 응용 프로그램이 충돌하거나 데이터가 손실될 수 있습니다.

CultureDefinition.Compile

CultureDefinition.Compile 메서드는 sysglobl.dll 어셈블리의 내부 System.Globalization.CultureDefinition 클래스의 멤버입니다. CultureDefinition.Compile은 사용자 지정 문화권에 대한 정보를 파일에 씁니다. 그러나 레지스트리에는 아무 것도 쓰지 않으므로 이 메서드를 사용하는 데는 관리 권한이 필요하지 않습니다.

구문

internal static void Compile(
   CultureAndRegionInfoBuilder builder,
   String outFile
);

매개 변수

  • builder
    읽을 CultureAndRegionInfoBuilder 개체입니다. 이 개체에 대한 조건은 CultureAndRegionInfoBuilder.Register의 경우와 동일합니다.

  • outFile
    출력 파일에 대한 전체 경로를 나타내는 문자열입니다. 이 메서드는 사용자 지정 culture 파일을 쓰지만 등록하지는 않습니다. 출력 파일에 포함된 사용자 지정 문화권 정의는 %windir%\globalization 디렉터리에 있더라도 인식되지 않습니다.

예외

지원되지 않는 전용 메서드이므로 모든 예외를 실패로 간주해야 합니다.

설명

다음은 CultureAndRegionInfoBuilder.Register와 CultureDefinition.Compile의 차이점입니다.

  • CultureAndRegionInfoBuilder.Register는 지원되는 일반 메서드입니다. 내부 메서드인 CultureDefinition.Compile은 이후 버전에서 변경되거나 제거될 수 있으므로 주의해서 사용해야 합니다.

  • CultureAndRegionInfoBuilder.Register를 사용하려면 관리 권한이 필요하지만 CultureDefinition.Compile에서는 작성 권한이 있는 모든 파일에 쓸 수 있습니다.

  • CultureAndRegionInfoBuilder.Register는CultureDefinition.Compile보다 더 많은 유효성 검사를 수행합니다. 따라서 CultureDefinition.Compile 메서드를 직접 호출하면 일반적인 방법으로는 컴퓨터에 설치할 수 없는 유효하지 않은 culture를 만들 수 있습니다. 생성된 culture에는 정형화되지 않은 데이터나 운영 체제 또는 .NET Framework 오류를 발생시킬 수 있는 데이터가 포함될 수 있습니다.

  • CultureAndRegionInfoBuilder.Register는 항상 %windir%\globalization 디렉터리에 출력 파일을 만듭니다. CultureDefinition.Compile은 지정한 모든 출력 파일에 씁니다.

  • builder 매개 변수에서 지정한 CultureAndRegionInfoBuilder 개체에 일관성이 없거나 예상하지 않은 데이터가 포함된 경우 CultureAndRegionInfoBuilder.Register에서 예외를 throw할 수 있습니다. 그러나 이 메서드는 CultureAndRegionInfoBuilder.Register만큼 철저하게 유효성 검사를 수행하지 않습니다.

    주의 정보주의

    CultureDefinition.Compile은 제한된 유효성 검사 메커니즘을 사용하므로 유효하지 않거나 일관성이 없는 culture를 만드는 경우가 있습니다. 이로 인해 응용 프로그램이 충돌하거나 데이터가 손실될 수 있습니다.

  • CultureAndRegionInfoBuilder.Register는 레지스트리에 사용자 지정 culture 파일을 등록합니다. CultureDefinition.Compile은 사용자 지정 culture를 만들지만 로컬 운영 체제에 이 사용자 지정 culture를 등록(설치)하지는 않습니다. %windir%\globalization 디렉터리에 등록되지 않은 파일은 실패하고 .NET Framework 4에서 정상적으로 작동하지 않습니다. 이러한 파일은 작동 가능한 상태로 나타날 수도 있지만 운영 체제 또는 .NET Framework에서 올바르게 등록되지 않은 사용자 지정 culture 파일을 액세스하면 잘못된 동작이나 실패가 발생할 수 있습니다.

  • CultureAndRegionInfoBuilder.Register 메서드를 호출하면 사용자 지정 culture 파일이 생성됩니다. 또한 문화권 이름을 지정하는 문자열 값을 만드는 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale 레지스트리 키를 설정합니다. CultureDefinition.Compile 메서드는 사용자 지정 culture 파일을 쓰지만 해당 레지스트리 키를 만들지는 않습니다.

    참고참고

    .NET Framework 버전 3.5부터 .NET Framework에서 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\IetfLanguage 레지스트리 키를 사용하지 않으므로 CultureDefinition.Compile 메서드는 더 이상 해당 키를 설정하지 않습니다.문화권 이름은 RFC 4646 맞게 수정되었습니다.

CultureDefinition.Compile 직접 사용

CultureDefinition.Compile을 사용하여 사용자 지정 culture를 저장하려면

  1. 필요한 유효성 검사를 수행할 코드를 응용 프로그램에 포함합니다. CultureDefinition.Compile 메서드를 직접 사용할 경우에는 CultureAndRegionInfoBuilder.Register 메서드에서 수행하는 유효성 검사가 수행되지 않는다는 점을 기억하십시오. 파일이 올바르지 않게 생성되면 결과 사용자 지정 culture 파일에 액세스할 수는 있더라도 올바르지 않거나 잘못된 동작이 발생할 수 있습니다.

  2. CultureAndRegionInfoBuilder.Register를 호출하는 대신 CultureDefinition.Compile 메서드를 호출한 다음 적절한 파일 이름과 함께 CultureAndRegionInfoBuilder 개체로 전달합니다.

  3. 다음 절차에 설명된 대로 결과 사용자 지정 culture 파일을 등록합니다.

사용자 지정 culture 파일 등록(설치)

사용자 지정 culture 파일을 등록(설치)하려면

  1. CultureDefinition.Compile 호출 결과를 %windir%\globalization 하위 디렉터리에 쓰는 코드를 응용 프로그램에 포함합니다.

  2. .NET Framework 4에서 실행할 때 사용자 지정 culture를 성공시키려면 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale 레지스트리 키에 쓰는 코드를 포함시킵니다.

예제

다음 예제에서는 CultureAndRegionInfoBuilder 클래스를 사용하여 다른 통화 기호($를 사용하지 않고 USD를 사용)를 사용하는 영어(미국) 문화권에 기초하여 이름이 x-en-US-example인 사용자 지정 문화권을 만듭니다. 이 예제는 개인 CultureDefinition.Compile 메서드를 호출하여 문화권 정의를 컴파일하기 위한 리플렉션을 사용합니다. 그런 다음 컴파일된 .nlp 파일을 Windows 디렉터리의 Globalization 하위 디렉터리에 복사한 다음 레지스트리에 사용자 지정 문화권을 등록합니다. 다음으로, 사용자 지정 문화권을 나타내는 CultureInfo 개체를 인스턴스화하고 이를 서식 지정 작업에 사용합니다. 마지막으로 예제는 CultureAndRegionInfoBuilder.Unregister 메서드를 호출하여 사용자 지정 문화권 정의를 제거합니다. 예제를 성공적으로 컴파일하려면 프로젝트에 sysglobl.dll에 대한 참조를 추가해야 합니다.

Imports Microsoft.Win32
Imports System.Globalization
Imports System.IO
Imports System.Reflection

Module Example
   Private Const MAX_PATH As Integer = 260
   Private Const CUSTOM_KEY As String = "SYSTEM\CurrentControlSet\Control\Nls\CustomLocale"
   Private Declare Function GetWindowsDirectory Lib "Kernel32" _
           Alias "GetWindowsDirectoryA" _ 
           (lpBuffer As String, nSize As Integer) As Integer

   Private cultureName As String = "x-en-US-example"

   Public Sub Main()
      ' Create an alternate en-US culture.
      Dim enUS As New CultureAndRegionInfoBuilder(cultureName, CultureAndRegionModifiers.None)
      enUS.LoadDataFromCultureInfo(CultureInfo.CreateSpecificCulture("en-US"))
      enUS.LoadDataFromRegionInfo(New RegionInfo("US"))
      enUS.NumberFormat.CurrencySymbol = "USD"
      enUS.NumberFormat.CurrencyPositivePattern = 2
      enUS.NumberFormat.CurrencyNegativePattern = 12

      ' Use reflection to get the CultureDefinition.Compile method.
      Dim assem As Assembly = Assembly.Load("sysglobl, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")            
      Dim defType As Type = assem.GetType("System.Globalization.CultureDefinition")
      Dim method As MethodInfo = defType.GetMethod("Compile", BindingFlags.NonPublic Or BindingFlags.Static)
      Dim tempPath As String = ".\" + cultureName + ".nlp"
      Dim args() As Object = { enUS, tempPath }

      ' Delete target file if it already exists.
      If File.Exists(tempPath) Then File.Delete(tempPath)

      ' Compile the culture definition.
      method.Invoke(Nothing, args)  

      ' Copy the file.
      Try
         Dim buffer As New String(ChrW(0), MAX_PATH)
         Dim charsWritten As Integer = GetWindowsDirectory(buffer, MAX_PATH)
         Dim fileName As String = String.Format("{0}{1}Globalization{1}{2}.nlp", 
                                                buffer.Substring(0, charsWritten),
                                                Path.DirectorySeparatorChar,
                                                cultureName) 
         File.Copy(tempPath, fileName, True)
         WriteToRegistry(CUSTOM_KEY, cultureName)       
      Catch e As UnauthorizedAccessException
         Console.WriteLine("You must run this application as an administrator")
         Console.WriteLine("so that you can install culture definition files.") 
         Exit Sub
      End Try

      ' Create and use the new culture.
      Try
         Dim value As Decimal = 1603.42d
         Dim ci As New CultureInfo(cultureName)
         Console.WriteLine(String.Format(ci, "{0:C2}", value))
      Catch e As CultureNotFoundException
         Console.WriteLine("Unable to create the '{0}' culture.", cultureName)
      End Try

      CultureAndRegionInfoBuilder.Unregister(cultureName)
   End Sub

   Public Sub WriteToRegistry(keyName As String, valueName As String)
      Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(keyName, True)
      ' Create the key if it does not already exist.
      If key Is Nothing      
         key = Registry.LocalMachine.CreateSubKey(keyName)
         If key Is Nothing Then Throw New NullReferenceException("Cannot create the registry key")
      End If
      ' Set the new name
      key.SetValue(valueName, valueName)
      key.Close()
   End Sub
End Module
' The example displays the following output:
'         USD 1,603.42
using Microsoft.Win32;
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

public class Example
{
   private const int MAX_PATH = 260;
   private const string CUSTOM_KEY = @"SYSTEM\CurrentControlSet\Control\Nls\CustomLocale";

   [DllImport("kernel32", SetLastError=true)]
   private static extern int GetWindowsDirectory(StringBuilder lpBuffer, 
                                                  int nSize);

   private static string cultureName = "x-en-US-example";

   public static void Main()
   {
      // Create an alternate en-US culture.
      CultureAndRegionInfoBuilder enUS = new CultureAndRegionInfoBuilder(cultureName, CultureAndRegionModifiers.None);
      enUS.LoadDataFromCultureInfo(CultureInfo.CreateSpecificCulture("en-US"));
      enUS.LoadDataFromRegionInfo(new RegionInfo("US"));
      enUS.NumberFormat.CurrencySymbol = "USD";
      enUS.NumberFormat.CurrencyPositivePattern = 2;
      enUS.NumberFormat.CurrencyNegativePattern = 12;

      // Use reflection to get the CultureDefinition.Compile method.
      Assembly assem = Assembly.Load("sysglobl, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");            
      Type defType = assem.GetType("System.Globalization.CultureDefinition");
      MethodInfo method = defType.GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Static);
      string tempPath = @".\" + cultureName + ".nlp";
      object[] args = { enUS, tempPath };
      // Delete target file if it already exists.
      if (File.Exists(tempPath))
         File.Delete(tempPath);

      // Compile the culture definition.
      method.Invoke(null, args);  
      // Copy the file.
      try {
         StringBuilder buffer = new StringBuilder(MAX_PATH);
         int charsWritten = GetWindowsDirectory(buffer, MAX_PATH);
         string fileName = String.Format("{0}{1}Globalization{1}{2}.nlp", 
                                         buffer.ToString().Substring(0, charsWritten),
                                         Path.DirectorySeparatorChar,
                                         cultureName); 
         File.Copy(tempPath, fileName, true);
         WriteToRegistry(CUSTOM_KEY, cultureName);       
      }
      catch (UnauthorizedAccessException) {
         Console.WriteLine("You must run this application as an administrator");
         Console.WriteLine("so that you can install culture definition files."); 
         return;
      }

      // Create and use the new culture.
      try {
         decimal value = 1603.42m;
         CultureInfo ci = new CultureInfo(cultureName);
         Console.WriteLine(String.Format(ci, "{0:C2}", value));
      }
      catch (CultureNotFoundException) {
         Console.WriteLine("Unable to create the '{0}' culture.", cultureName);
      }

      CultureAndRegionInfoBuilder.Unregister(cultureName);
   }

   public static void WriteToRegistry(string keyName, string valueName)
   {
      RegistryKey key = Registry.LocalMachine.OpenSubKey(keyName, true);
      // Create the key if it does not already exist.
      if (key == null) {      
         key = Registry.LocalMachine.CreateSubKey(keyName);
         if (key == null) throw new NullReferenceException("Cannot create the registry key");
      }
      // Set the new name
      key.SetValue(valueName, valueName);
      key.Close();
   }
}
// The example displays the following output:
//        USD 1,603.42

참고 항목

작업

방법: 사용자 지정 Culture 만들기

변경 기록

날짜

변경 내용

이유

2010년 12월

.NET Framework에 대해 수정하고 예제를 추가했습니다.

향상된 기능 관련 정보