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.
Cuidado |
---|
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:
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.
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.
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:
Incluir o código em seu aplicativo para gravar a saída da CultureDefinition.Compile de chamada para o subdiretório %windir%\globalization.
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. |