Condividi tramite


Procedura: salvare impostazioni cultura personalizzate senza privilegi amministrativi

In questo argomento viene descritta una tecnica per salvare i dati di impostazioni cultura personalizzate in un file senza privilegi amministrativi. Tramite un'applicazione eseguita con privilegi amministrativi vengono registrate impostazioni cultura personalizzate utilizzando il metodo CultureAndRegionInfoBuilder.Register, come descritto nell'argomento Procedura: creare impostazioni cultura personalizzate. Tramite questo metodo, viene chiamato internamente il metodo CultureDefinition.Compile, per il quale non sono richiesti privilegi amministrativi.

Per salvare impostazioni cultura personalizzate senza privilegi amministrativi, è possibile accedere al metodo CultureDefinition.Compile direttamente utilizzando la reflection.

Nota di avvisoAttenzione

La chiamata diretta del metodo CultureDefinition.Compile non è supportata.Il metodo può essere modificato o persino rimosso senza avviso.In questo argomento viene descritto solo il comportamento di .NET Framework versione 4.Se il metodo viene utilizzato in modo improprio, il computer potrebbe trovarsi in uno stato di instabilità, con il rischio di possibili arresti anomali delle applicazioni o di perdita di dati.

Informazioni su CultureDefinition.Compile

Il metodo CultureDefinition.Compile è un membro della classe System.Globalization.CultureDefinition interna nell'assembly sysglobl.dll. Il metodo CultureDefinition.Compile consente di scrivere in un file le informazioni su impostazioni cultura personalizzate. Poiché tuttavia non viene scritta alcuna informazione nel Registro di sistema, non sono richiesti privilegi amministrativi.

Sintassi

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

Parametri

  • builder
    Oggetto CultureAndRegionInfoBuilder da leggere. Le condizioni per questo oggetto sono identiche a quelle per l'oggetto CultureAndRegionInfoBuilder.Register.

  • outFile
    Stringa che rappresenta il percorso completo del file di output. Il metodo consente la scrittura del file delle impostazioni cultura personalizzate, ma non la registrazione. La definizione delle impostazioni cultura personalizzate contenuta nel file di output non sarà riconosciuta persino se viene posizionata nella directory %windir%\globalization.

Eccezioni

Poiché si tratta di un metodo privato non supportato, qualsiasi eccezione deve essere considerata un errore.

Note

Di seguito sono indicate le differenze tra CultureAndRegionInfoBuilder.Register e CultureDefinition.Compile:

  • CultureAndRegionInfoBuilder.Register è un metodo pubblico supportato. Poiché si tratta di un metodo interno, CultureDefinition.Compile è soggetto a modifica o alla rimozione nelle versioni future, pertanto non deve essere considerato affidabile.

  • Per il metodo CultureAndRegionInfoBuilder.Register sono necessarie autorizzazioni amministrative, ma l'oggetto CultureDefinition.Compile consente di scrivere in qualsiasi file su cui l'utente dispone dell'autorizzazione per la creazione.

  • Il metodo CultureAndRegionInfoBuilder.Register consente di eseguire un numero maggiore di controlli di convalida rispetto a CultureDefinition.Compile. Chiamando pertanto direttamente quest'ultimo metodo, si rischia di creare impostazioni cultura non valide, normalmente non installabili in un computer. Le impostazioni cultura create potrebbero contenere dati non corretti o dati che possono causare un malfunzionamento del sistema operativo o di .NET Framework.

  • Il file di output creato dal metodo CultureAndRegionInfoBuilder.Register viene sempre collocato nella directory %windir%\globalization. Il metodo CultureDefinition.Compile consente di scrivere in qualsiasi file di output specificato.

  • È possibile che tramite il metodo CultureAndRegionInfoBuilder.Register venga generata un'eccezione se nell'oggetto CultureAndRegionInfoBuilder specificato dal parametro builder sono contenuti dati incoerenti o imprevisti. Tuttavia, questo metodo non esegue una convalida accurata quanto il metodo CultureAndRegionInfoBuilder.Register.

    Nota di avvisoAttenzione

    Poiché in CultureDefinition.Compile vengono utilizzati meccanismi di convalida limitati, è possibile che le impostazioni cultura create tramite questo metodo non siano valide oppure risultino incoerenti e causando, di conseguenza, arresti anomali dell'applicazione o persino la perdita di dati.

  • Il metodo CultureAndRegionInfoBuilder.Register consente di registrare il file impostazioni cultura personalizzate nel Registro di sistema. CultureDefinition.Compile crea impostazioni cultura personalizzate, ma non le registra, ovvero non le installa, nel sistema operativo locale. I file non registrati nella directory %windir%\globalization non sono completamente funzionali in .NET Framework 4. Benché possano sembrare eseguibili, i file delle impostazioni cultura personalizzate registrati in modo non adeguato possono dar luogo a comportamenti inconsueti o a errori se vi si accede dal sistema operativo o da .NET Framework.

  • Quando si chiama il metodo CultureAndRegionInfoBuilder.Register, viene creato il file impostazioni cultura personalizzate. Viene inoltre impostata la chiave del Registro di sistema HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale, per la quale viene creato un valore stringa tramite il quale viene assegnato un nome alle impostazioni cultura. Tramite il metodo CultureDefinition.Compile viene creato il file delle impostazioni cultura personalizzate, ma non viene creata la chiave del Registro di sistema corrispondente.

    NotaNota

    A partire da .NET Framework versione 3.5, il metodo CultureDefinition.Compile non consente più l'impostazione della chiave HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\IetfLanguage del Registro di sistema in quanto la chiave non è utilizzata in .NET Framework.I nomi delle impostazioni cultura sono stati corretti in conformità a RFC 4646.

Utilizzo diretto di CultureDefinition.Compile

Per salvare impostazioni cultura personalizzate utilizzando CultureDefinition.Compile:

  1. Includere il codice nell'applicazione per eseguire le eventuali convalide necessarie. Si ricordi che le convalide eseguite dal metodo CultureAndRegionInfoBuilder.Register non vengono eseguite quando si utilizza direttamente il metodo CultureDefinition.Compile. Sebbene il file delle impostazioni cultura personalizzate risultanti risultano accessibili, i file creati in modo non appropriato potrebbero presentare un comportamento non valido o inconsueto.

  2. Anziché chiamare il metodo CultureAndRegionInfoBuilder.Register, chiamare il metodo CultureDefinition.Compile e passarlo all'oggetto CultureAndRegionInfoBuilder insieme a un nome file appropriato.

  3. Registrare il file delle impostazioni cultura personalizzate risultanti come descritto nella procedura che segue.

Registrazione (installazione) del file delle impostazioni cultura personalizzate

Per registrare, ovvero installare, il file delle impostazioni cultura personalizzate:

  1. Includere nell'applicazione il codice per scrivere l'output della chiamata a CultureDefinition.Compile nella sottodirectory %windir%\globalization.

  2. Per consentire l'applicazione delle impostazioni cultura personalizzate durante l'esecuzione in .NET Framework 4, includere il codice per la scrittura nella chiave del Registro di sistema HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CustomLocale.

Esempio

Nell'esempio seguente viene utilizzata la classe CultureAndRegionInfoBuilder per creare impostazioni cultura personalizzate denominate x-en-US-example basate sulle impostazioni cultura Inglese (Stati Uniti) ma nelle quali si utilizza un simbolo di valuta diverso (USD invece di $). Nell'esempio viene utilizzata la reflection per compilare la definizione delle impostazioni cultura mediante la chiamata al metodo CultureDefinition.Compile. Il file con estensione npl compilato viene quindi copiato nella sottodirectory Globalization della directory di Windows e vengono registrate le impostazioni cultura personalizzate nel Registro di sistema. Successivamente, viene creata un'istanza di un oggetto CultureInfo tramite cui vengono rappresentate le impostazioni cultura personalizzate che vengono utilizzate in un'operazione di formattazione. Infine, nell'esempio viene chiamato il metodo CultureAndRegionInfoBuilder.Unregister per rimuovere la definizione delle impostazioni cultura personalizzate. Si noti che per compilare correttamente l'esempio, è necessario aggiungere al progetto un riferimento a 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

Vedere anche

Attività

Procedura: creare impostazioni cultura personalizzate

Cronologia delle modifiche

Data

Cronologia

Motivo

Dicembre 2010

Revisionato per .NET Framework 4 con l'aggiunta di un esempio.

Miglioramento delle informazioni.