Partilhar via


Como: Salvar a culturas personalizadas sem privilégios administrativos

Este tópico descreve uma técnica para salvar dados de cultura personalizada em um arquivo sem privilégios administrativos. Um aplicativo que está sendo executado com privilégios administrativos registra uma cultura personalizada usando o CultureAndRegionInfoBuilder.Register método, conforme descrito no tópico Como: Criar personalizado culturas. Este método chama internamente o CultureDefinition.Compile método, que não requer privilégios administrativos.

Para salvar as culturas personalizadas sem privilégios administrativos, você pode usar a reflexão para acessar o CultureDefinition.Compile método diretamente.

Observação de cuidadoCuidado

Chamar o CultureDefinition.Compile método diretamente é suportado.O método pode alterar ou até mesmo ser removido sem aviso prévio.Este tópico descreve o seu comportamento para o .NET Framework versão 4 somente.Mau uso desse método pode deixar seu computador em um estado instável, possivelmente resultando em perda de dados ou falhas de aplicativo.

Sobre CultureDefinition.Compile

O CultureDefinition.Compile método é um membro de internos System.Globalization.CultureDefinition classe no assembly sysglobl. dll. CultureDefinition.Compilegrava informações sobre uma cultura personalizada em um arquivo. No entanto, porque ele não grava nada no registro, ele não exigem privilégios administrativos.

Sintaxe

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

Parâmetros

  • builder
    O CultureAndRegionInfoBuilder o objeto para leitura. As condições neste objeto são as mesmas do CultureAndRegionInfoBuilder.Register.

  • outFile
    Um string que representa o caminho completo para o arquivo de saída. O método grava o arquivo de cultura personalizada mas não registrar. A definição da cultura personalizada contida no arquivo de saída não será reconhecida, mesmo se ele é colocado no diretório %windir%\globalization.

Exceções

Como este é um método particular não suportado, qualquer exceção deve ser considerada uma falha.

Comentários

A seguir é as diferenças entre CultureAndRegionInfoBuilder.Register e CultureDefinition.Compile:

  • CultureAndRegionInfoBuilder.Registeré um método público com suporte. Como um método interno, CultureDefinition.Compile está sujeito a alteração ou remoção em futuras versões e não deve ser considerado.

  • CultureAndRegionInfoBuilder.Registerrequer permissões administrativas, mas CultureDefinition.Compile grava a qualquer arquivo, o usuário tem permissão para criar.

  • CultureAndRegionInfoBuilder.Registerexecuta a validação de mais de CultureDefinition.Compile. Portanto, chamar diretamente o último método pode criar uma cultura inválida, normalmente não pode ser instalada em um computador. A cultura criada pode conter dados irregulares ou dados que podem fazer com que o sistema operacional ou o.NET Framework para falhar.

  • CultureAndRegionInfoBuilder.Registersempre cria o arquivo de saída no diretório %windir%\globalization. CultureDefinition.Compilegrava em qualquer arquivo de saída especificado.

  • CultureAndRegionInfoBuilder.Registerpode lançar uma exceção se a CultureAndRegionInfoBuilder objeto especificado pelo builder parâmetro contém dados inconsistentes ou inesperado. No entanto, esse método não valida tão exaustivamente como CultureAndRegionInfoBuilder.Register.

    Observação

    Porque CultureDefinition.Compile usa limitada de mecanismos de validação, ele pode criar culturas inválidas ou inconsistentes, potencialmente, levando a falhas do aplicativo ou até mesmo a perda de dados.

  • CultureAndRegionInfoBuilder.Registerregistra o arquivo de cultura personalizada no registro. CultureDefinition.Compile cria uma cultura personalizada mas não registra (instalar)-o em um sistema operacional local. Arquivos não registrados no diretório %windir%\globalization falhar e não são totalmente funcionais de .NET Framework 4. Embora eles aparecerem operável, registrado incorretamente cultura personalizada de arquivos podem causar comportamento imprevisível ou falhas se acessado pelo sistema operacional ou pela.NET Framework.

  • Quando você chama o CultureAndRegionInfoBuilder.Register método, ele cria o arquivo de cultura personalizada. Ele também define a chave do registro HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale, para o qual ele cria um valor de seqüência de caracteres que nomeia a cultura. O CultureDefinition.Compile método cria o arquivo de cultura personalizada, mas não cria a chave de registro correspondente.

    Observação

    Começando com o .NET Framework versão 3.5, o CultureDefinition.Compile método não define a chave de registro HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\IetfLanguage, porque a chave não é usada pelo.NET Framework.Os nomes de cultura foram corrigidos de acordo com a RFC 4646.

Usando diretamente o CultureDefinition.Compile

Para salvar as culturas personalizadas usando CultureDefinition.Compile:

  1. Inclua o código em seu aplicativo para executar as validações necessárias. Lembre-se de que as validações executada pela CultureAndRegionInfoBuilder.Register método não são executadas quando você usa o CultureDefinition.Compile método diretamente. Embora o arquivo resultante da cultura personalizada poderão ser acessado, arquivos construídos incorretamente podem apresentar um comportamento ilegal ou irregular.

  2. Em vez de chamada CultureAndRegionInfoBuilder.Register, chame o CultureDefinition.Compile método e passá-lo a CultureAndRegionInfoBuilder objeto juntamente com um nome de arquivo apropriado.

  3. Registre o arquivo resultante da cultura personalizada, conforme descrito no próximo procedimento.

Registrando (instalar) o arquivo de cultura personalizada

Para registrar a cultura personalizada (instalar) arquivo:

  1. Incluir o código em seu aplicativo para gravar a saída da CultureDefinition.Compile de chamada para o subdiretório %windir%\globalization.

  2. Para habilitar a cultura personalizada bem-sucedidas quando executando sob o .NET Framework 4, inclua o código para gravar a chave de registro HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale.

Exemplo

O exemplo a seguir usa a CultureAndRegionInfoBuilder classe para criar uma cultura personalizada denominada x-en-US-example que se baseia a cultura do inglês (Estados Unidos), mas usa um símbolo de moeda diferente (USD em vez de $). O exemplo usa a reflexão para compilar a definição de cultura chamando particular CultureDefinition.Compile método. Em seguida, ele copia o compilado. arquivo NLP no subdiretório do diretório do Windows e registradores de cultura personalizada no registro de globalização. Em seguida, ele instancia um CultureInfo o objeto que representa a cultura personalizada e o utiliza em uma operação de formatação. Finalmente, o exemplo chama o CultureAndRegionInfoBuilder.Unregister método para remover a definição da cultura personalizada. Observe que uma referência a sysglobl. dll deve ser adicionada ao projeto para compilar com êxito o exemplo.

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

Consulte também

Tarefas

Como: Criar personalizado culturas

Histórico de alterações

Date

History

Motivo

Dezembro de 2010

Revisado para o.NET Framework 4 e adicionou um exemplo.

Aprimoramento de informações.