Creación de ensamblados satélite para aplicaciones .NET

Los archivos de recursos desempeñan un papel fundamental en las aplicaciones localizadas. Permiten que una aplicación muestre cadenas, imágenes y otros datos en el idioma y la referencia cultural del usuario, y que proporcione datos alternativos si los recursos del idioma o la referencia cultural del usuario no están disponibles. .NET usa un modelo de concentrador y radio para buscar y recuperar recursos localizados. El concentrador es el ensamblado principal que contiene el código ejecutable no localizable y los recursos de una referencia cultural única, denominada referencia cultural neutra o predeterminada. La referencia cultural predeterminada es la referencia cultural de reserva de la aplicación; se usa si no hay recursos localizados disponibles. El atributo NeutralResourcesLanguageAttribute se usa para designar la referencia cultural predeterminada de la aplicación. Cada radio se conecta a un ensamblado satélite que contiene los recursos de una única referencia cultural localizada, pero no contiene código. Debido a que los ensamblados satélite no forman parte del ensamblado principal, los recursos correspondientes a una referencia cultural específica se pueden actualizar o reemplazar fácilmente sin reemplazar el ensamblado principal de la aplicación.

Nota

Los recursos de la referencia cultural predeterminada de una aplicación también se pueden almacenar en un ensamblado satélite. Para ello, asigne al atributo NeutralResourcesLanguageAttribute un valor de UltimateResourceFallbackLocation.Satellite.

Nombre y ubicación del ensamblado satélite

El modelo de concentrador y radio requiere colocar recursos en ubicaciones específicas para que sea fácil ubicarlos y usarlos. Si no compila los recursos ni les asigna nombre de la manera prevista, o si no los coloca en las ubicaciones correctas, Common Language Runtime no puede localizarlos y usa en su lugar los recursos de la referencia cultural predeterminada. El administrador de recursos de .NET se representa mediante el tipo ResourceManager y se usa para acceder automáticamente a los recursos localizados. El administrador de recursos requiere lo siguiente:

  • Todos los recursos de una referencia cultural determinada deben estar incluidos en un solo ensamblado satélite. En otras palabras, debe compilar varios archivos .txt o .resx en un solo archivo .resources binario.

  • Debe haber un subdirectorio independiente en el directorio de la aplicación para cada referencia cultural localizada que almacena los recursos de esa referencia cultural. El nombre del subdirectorio debe ser el mismo que el nombre de la referencia cultural. Como alternativa, puede almacenar los ensamblados satélite en la caché global de ensamblados. En este caso, el componente de información de referencia cultural del nombre seguro del ensamblado debe indicar su referencia cultural. Para obtener más información, consulte Instalación de ensamblados satélite en la caché global de ensamblados.

    Nota

    Si la aplicación incluye recursos para referencias culturales secundarias, coloque cada una de ellas en un subdirectorio independiente bajo el directorio de la aplicación. No coloque las referencias culturales secundarias en subdirectorios bajo el directorio de la referencia cultural principal.

  • El ensamblado satélite debe tener el mismo nombre que la aplicación y debe usar la extensión de nombre de archivo ".resources.dll". Por ejemplo, si una aplicación se denomina Example.exe, el nombre de cada ensamblado satélite debe ser Example.resources.dll. El nombre del ensamblado satélite no indica la referencia cultural de sus archivos de recursos. Aun así, el ensamblado satélite aparece en un directorio que especifica la referencia cultural.

  • La información sobre la referencia cultural del ensamblado satélite debe incluirse en los metadatos del ensamblado. Para almacenar el nombre de la referencia cultural en los metadatos del ensamblado satélite, especifique la opción /culture cuando use Assembly Linker para insertar recursos en el ensamblado satélite.

En la ilustración siguiente se muestra una estructura de directorios de ejemplo y los requisitos de localización de las aplicaciones que no se instalan en la caché global de ensamblados. Los elementos con las extensiones .txt y .resources no se incluyen en la aplicación final. Estos son los archivos de recursos intermedios que se usan para crear los ensamblados de recursos satélite finales. En este ejemplo, los archivos .resx se pueden sustituir por archivos .txt. Para obtener más información, consulte Empaquetar e implementar recursos.

La imagen siguiente muestra el directorio del ensamblado satélite:

Un directorio de ensamblado satélite con subdirectorios de referencias culturas localizadas.

Compilación de ensamblados satélite

Use el generador de archivos de recursos (Resgen.exe) para compilar archivos de texto o archivos XML ( .resx) que contienen recursos en archivos .resources binarios. Después, use Assembly Linker (al.exe) para compilar archivos .resources en ensamblados satélite. al.exe crea un ensamblado a partir de los archivos .resources que especifique. Los ensamblados satélite solo pueden contener recursos; no pueden contener código ejecutable.

El comando de al.exe a continuación crea un ensamblado satélite para la aplicación Example a partir del archivo de recursos de alemán strings.de.resources.

al -target:lib -embed:strings.de.resources -culture:de -out:Example.resources.dll

El comando de al.exe a continuación también crea un ensamblado satélite para la aplicación Example a partir del archivo strings.de.resources. La opción /template hace que el ensamblado satélite herede todos los metadatos del ensamblado salvo la información de referencia cultural del ensamblado principal (Example.dll).

al -target:lib -embed:strings.de.resources -culture:de -out:Example.resources.dll -template:Example.dll

En la tabla siguiente se describen detalladamente las opciones de al.exe usadas en estos comandos:

Opción Descripción
-target:lib Especifica que el ensamblado satélite se compila en un archivo de biblioteca (.dll). Dado que un ensamblado satélite no contiene código ejecutable y no es el ensamblado principal de una aplicación, debe guardar los ensamblados satélite como archivos DLL.
-embed:strings.de.resources Especifica el nombre del archivo de recursos que se va a insertar cuando al.exe compile el ensamblado. Puede insertar varios archivos .resources en un ensamblado satélite, pero si sigue el modelo de concentrador y radio, debe compilar un ensamblado satélite para cada referencia cultural. Aun así, puede crear archivos .resources independientes para cadenas y objetos.
-culture:de Especifica la referencia cultural del recurso que se va a compilar. Common Language Runtime usa esta información cuando busca los recursos para la referencia cultural especificada. Si se omite esta opción, al.exe compila igualmente el recurso, pero el runtime no puede encontrarlo cuando un usuario lo solicita.
-out:Example.resources.dll Especifica el nombre del archivo de salida. El nombre debe seguir la convención de nomenclatura baseName.resources.extension, donde baseName es el nombre del ensamblado principal y extension es una extensión de nombre de archivo válida (por ejemplo, .dll). El runtime no puede determinar la referencia cultural de un ensamblado satélite en función del nombre de su archivo de salida; debe usar la opción /culture para ello.
-template:Example.dll Especifica el ensamblado del que el ensamblado satélite heredará todos los metadatos de ensamblado, salvo el campo correspondiente a la referencia cultural. Esta opción solo afecta a los ensamblados satélite si se especifica un ensamblado con nombre seguro.

Para obtener una lista completa de las opciones disponibles con al.exe, consulte Assembly Linker (al.exe).

Nota

Puede haber ocasiones en las que quiera usar la tarea MSBuild de .NET Core para compilar ensamblados satélite, aunque tenga como destino .NET Framework. Por ejemplo, es posible que quiera usar la opción deterministic del compilador de C# para poder comparar ensamblados de diferentes compilaciones. En este caso, establezca GenerateSatelliteAssembliesForCore en true en el archivo .csproj para generar ensamblados satélite mediante csc.exe en lugar de Al.exe (Assembly Linker).

<Project>
    <PropertyGroup>
        <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
    </PropertyGroup>
</Project>

La tarea MSBuild de .NET Core usa csc.exe en lugar de al.exe para generar ensamblados satélite de manera predeterminada. Para obtener más información, consulte Facilitar la participación en la generación de ensamblados satélite "Core".

Ejemplo de ensamblados satélite

A continuación se incluye un ejemplo sencillo de "Hola a todos" que muestra un cuadro de mensaje con un saludo localizado. El ejemplo incluye recursos para las referencias culturales de inglés (Estados Unidos), francés (Francia) y ruso (Rusia), y su referencia cultural de reserva es inglés. Para crear este ejemplo, haga lo siguiente:

  1. Cree un archivo de recursos denominado Greeting.resx o Greeting.txt para que contenga el recurso para la referencia cultural predeterminada. Almacene una sola cadena de nombre HelloString cuyo valor sea "Hola mundo" en este archivo.

  2. Para indicar que el inglés (en) es la referencia cultural predeterminada de la aplicación, agregue el siguiente atributo System.Resources.NeutralResourcesLanguageAttribute al archivo AssemblyInfo de la aplicación o al archivo de código fuente principal que se compilará en el ensamblado principal de la aplicación.

    [assembly: NeutralResourcesLanguage("en")]
    
    <Assembly: NeutralResourcesLanguage("en")>
    
  3. Agregue compatibilidad para referencias culturales adicionales (en-US, fr-FR y ru-RU) a la aplicación de la manera siguiente:

    • Para admitir la referencia cultural en-US o inglés (Estados Unidos), cree un archivo de recursos denominado Greeting.en-US.resx o Greeting.en-US.txt y almacene en él una sola cadena denominada HelloString cuyo valor sea "Hi world!".

    • Para admitir la referencia cultural fr-FR o francés (Francia), cree un archivo de recursos denominado Greeting.fr-FR.resx o Greeting.fr-FR.txt y almacene en él una sola cadena denominada HelloString cuyo valor sea "Salut tout le monde!".

    • Para admitir la referencia cultural ru-RU o ruso (Rusia), cree un archivo de recursos denominado Greeting.ru-RU.resx o Greeting.ru-RU.txt y almacene en él una sola cadena denominada HelloString cuyo valor sea "Всем привет!".

  4. Use resgen.exe para compilar cada texto o archivo de recursos XML en un archivo .resources binario. La salida es un conjunto de archivos que tienen el mismo nombre de archivo raíz, como los archivos .resx o .txt, pero con una extensión .resources. Si crea el ejemplo con Visual Studio, el proceso de compilación se realiza automáticamente. Si no está usando Visual Studio, ejecute los comandos siguientes para compilar los archivos .resx en archivos .resources:

    resgen Greeting.resx
    resgen Greeting.en-us.resx
    resgen Greeting.fr-FR.resx
    resgen Greeting.ru-RU.resx
    

    Si los recursos se encuentran en archivos de texto en lugar de archivos XML, cambie la extensión .resx a .txt.

  5. Compile el código fuente siguiente junto con los recursos para la referencia cultural predeterminada en el ensamblado principal de la aplicación:

    Importante

    Si usa la línea de comandos en lugar de Visual Studio para crear el ejemplo, debe modificar la llamada al constructor de clase ResourceManager de la siguiente manera: ResourceManager rm = new ResourceManager("Greeting", typeof(Example).Assembly);

    using System;
    using System.Globalization;
    using System.Reflection;
    using System.Resources;
    using System.Threading;
    using System.Windows.Forms;
    
    class Example
    {
       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;
    
          try {
             CultureInfo newCulture = new CultureInfo(cultures[cultureNdx]);
             Thread.CurrentThread.CurrentCulture = newCulture;
             Thread.CurrentThread.CurrentUICulture = newCulture;
             ResourceManager rm = new ResourceManager("Example.Greeting",
                                                      typeof(Example).Assembly);
             string greeting = String.Format("The current culture is {0}.\n{1}",
                                             Thread.CurrentThread.CurrentUICulture.Name,
                                             rm.GetString("HelloString"));
    
             MessageBox.Show(greeting);
          }
          catch (CultureNotFoundException e) {
             Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName);
          }
          finally {
             Thread.CurrentThread.CurrentCulture = originalCulture;
             Thread.CurrentThread.CurrentUICulture = originalCulture;
          }
       }
    }
    
    Imports System.Globalization
    Imports System.Resources
    Imports System.Threading
    
    Module Module1
    
        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
    
            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, My.Resources.Greetings.HelloString)
    
                MsgBox(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
    

    Si el nombre de la aplicación es Example y se está compilando desde la línea de comandos, el comando del compilador de C# es:

    csc Example.cs -res:Greeting.resources
    

    El comando de compilador de Visual Basic correspondiente es el siguiente:

    vbc Example.vb -res:Greeting.resources
    
  6. Cree un subdirectorio en el directorio principal de la aplicación para cada referencia cultural localizada admitida por la aplicación. Debe crear un subdirectorio en-US, fr-FR y ru-RU. Visual Studio crea estos subdirectorios automáticamente como parte del proceso de compilación.

  7. Inserte los archivos .resources individuales específicos de la referencia cultural en ensamblados satélite y guárdelos en el directorio adecuado. El comando para hacer esto para cada archivo .resources es el siguiente:

    al -target:lib -embed:Greeting.culture.resources -culture:culture -out:culture\Example.resources.dll
    

    donde culture es el nombre de la referencia cultural cuyos recursos contiene el ensamblado satélite. Visual Studio controla este proceso automáticamente.

Después, ya puede ejecutar el ejemplo. Seleccionará aleatoriamente como referencia cultural actual una de las referencias culturales admitidas y mostrará un saludo localizado.

Instalación de ensamblados satélite en la caché global de ensamblados

En lugar de instalar los ensamblados en el subdirectorio de una aplicación local, puede instalarlos en la caché global de ensamblados. Esto es especialmente útil si tiene bibliotecas de clases y ensamblados de recursos de bibliotecas de clases que usan varias aplicaciones.

Para instalar ensamblados en la caché global de ensamblados, es necesario que tengan nombres seguros. Los ensamblados con nombre seguro se firman con un par de claves pública y privada válido. Contienen información de versión que el tiempo de ejecución usa para determinar qué ensamblado debe usar para atender a una solicitud de enlace. Para obtener más información sobre los nombres seguros y las versiones, consulte Versiones de los ensamblados. Para obtener más información sobre los nombres seguros, consulte Ensamblados con nombre seguro.

Cuando esté desarrollando una aplicación, es poco probable que tenga acceso al par de claves pública y privada final. Para instalar un ensamblado satélite en la caché global de ensamblados y asegurarse de que funciona según lo previsto, puede usar una técnica conocida como firma retrasada. Cuando se retrasa la firma de un ensamblado, en tiempo de compilación se reserva espacio en el archivo para la firma de nombre seguro. La firma real se retrasa hasta más adelante, cuando esté disponible el par de claves pública y privada final. Para obtener más información sobre la firma retardada, consulte Retraso de la firma de un ensamblado.

Obtención de la clave pública

Para retrasar la firma de un ensamblado, debe tener acceso a la clave pública. Puede obtener la clave pública real de la organización que se encargará de la firma o bien puede crear una clave pública mediante la herramienta de nombre seguro (sn.exe).

El siguiente comando de Sn.exe crea un par de claves pública y privada de prueba. La opción –k especifica que Sn.exe debe crear un par de claves y guardarlo en un archivo denominado TestKeyPair.snk.

sn –k TestKeyPair.snk

Puede extraer la clave pública del archivo que contiene el par de claves de prueba. El siguiente comando extrae la clave pública de TestKeyPair.snk y la guarda en PublicKey.snk:

sn –p TestKeyPair.snk PublicKey.snk

Retraso de la firma de un ensamblado

Después de obtener o crear la clave pública, use Assembly Linker (al.exe) para compilar el ensamblado y especificar la firma retardada.

El comando siguiente de al.exe crea un ensamblado satélite con nombre seguro para la aplicación StringLibrary a partir del archivo strings.ja.resources:

al -target:lib -embed:strings.ja.resources -culture:ja -out:StringLibrary.resources.dll -delay+ -keyfile:PublicKey.snk

La opción -delay+ especifica que Assembly Linker debe retrasar la firma del ensamblado. La opción -keyfile especifica el nombre del archivo de claves que contiene la clave pública que se va a usar para retrasar la firma del ensamblado.

Volver a firmar un ensamblado

Antes de implementar la aplicación, debe volver a firmar el ensamblado satélite con firma retrasada mediante el par de claves real. Para ello, use Sn.exe.

El siguiente comando de Sn.exe firma StringLibrary.resources.dll con el par de claves almacenado en el archivo RealKeyPair.snk. La opción –R especifica que se debe volver a firmar un ensamblado ya firmado o con firma retrasada.

sn –R StringLibrary.resources.dll RealKeyPair.snk

Instalación de un ensamblado satélite en la caché global de ensamblados

Cuando el tiempo de ejecución busca recursos en el proceso de reserva de recursos, busca primero en la caché global de ensamblados. (Para obtener más información, vea la sección "Proceso de reserva de recursos" de Empaquetado e implementación de recursos). En cuanto un ensamblado satélite se firma con un nombre seguro, se puede instalar en la caché global de ensamblados mediante la herramienta Caché global de ensamblados (gacutil.exe).

El siguiente comando de Gacutil.exe instala StringLibrary.resources.dll* en la memoria caché global de ensamblados:

gacutil -i:StringLibrary.resources.dll

La opción /i especifica que Gacutil.exe debe instalar el ensamblado especificado en la memoria caché global de ensamblados. Una vez que se ha instalado el ensamblado satélite en la caché, los recursos que contiene están disponibles para todas las aplicaciones que están diseñadas para usar el ensamblado satélite.

Recursos en la caché global de ensamblados: Un ejemplo

En el ejemplo siguiente se usa un método de una biblioteca de clases de .NET para extraer y devolver un saludo localizado de un archivo de recursos. La biblioteca y sus recursos están registrados en la caché global de ensamblados. El ejemplo incluye recursos para las referencias culturales de inglés (Estados Unidos), francés (Francia), ruso (Rusia) e inglés. El inglés es la referencia cultural predeterminada y sus recursos están almacenados en el ensamblado principal. En el ejemplo inicialmente se retrasa la firma de la biblioteca y sus ensamblados satélite con una clave pública, luego se vuelven a firmar con un par de claves pública y privada. Para crear este ejemplo, haga lo siguiente:

  1. Si no está usando Visual Studio, use el siguiente comando Sn.exe (Herramienta de nombre seguro) para crear un par de claves pública y privada de nombre ResKey.snk:

    sn –k ResKey.snk
    

    Si está usando Visual Studio, use la pestaña Firma del cuadro de diálogo Propiedades del proyecto para generar el archivo de claves.

  2. Use el siguiente comando de la herramienta de nombre seguro (Sn.exe) para crear un archivo de clave pública denominado PublicKey.snk:

    sn –p ResKey.snk PublicKey.snk
    
  3. Cree un archivo de recursos denominado Strings.resx para que contenga el recurso para la referencia cultural predeterminada. Almacene una sola cadena de nombre Greeting cuyo valor sea "¿Qué tal?" en ese archivo.

  4. Para indicar que "en" es la referencia cultural predeterminada de la aplicación, agregue el siguiente atributo System.Resources.NeutralResourcesLanguageAttribute al archivo AssemblyInfo de la aplicación o al archivo de código fuente principal que se compilará en el ensamblado principal de la aplicación:

    [assembly:NeutralResourcesLanguageAttribute("en")]
    
    <Assembly: NeutralResourcesLanguageAttribute("en")>
    
  5. Agregue compatibilidad para referencias culturales adicionales (en-US, fr-FR y ru-RU) a la aplicación de la manera siguiente:

    • Para admitir la referencia cultural "en-US" o inglés (Estados Unidos), cree un archivo de recursos denominado Strings.en-US.resx o Strings.en-US.txt y almacene en él una sola cadena denominada Greeting cuyo valor sea "Hello!".

    • Para admitir la referencia cultural "fr-FR" o francés (Francia), cree un archivo de recursos denominado Strings.fr-FR.resx o Strings.fr-FR.txt y almacene en él una sola cadena denominada Greeting cuyo valor sea "Bonjour!".

    • Para admitir la referencia cultural "ru-RU" o ruso (Rusia), cree un archivo de recursos denominado Strings.ru-RU.resx o Strings.ru-RU.txt y almacene en él una sola cadena denominada Greeting cuyo valor sea "Привет!".

  6. Use resgen.exe para compilar cada texto o archivo de recursos XML en un archivo .resources binario. La salida es un conjunto de archivos que tienen el mismo nombre de archivo raíz, como los archivos .resx o .txt, pero con una extensión .resources. Si crea el ejemplo con Visual Studio, el proceso de compilación se realiza automáticamente. Si no está usando Visual Studio, ejecute el comando siguiente para compilar los archivos .resx en archivos .resources:

    resgen filename
    

    Donde filename es la ruta de acceso opcional, el nombre de archivo y la extensión del archivo .resx o de texto.

  7. Compile el siguiente código fuente para StringLibrary.vb o StringLibrary.cs junto con los recursos para la referencia cultural predeterminada en un ensamblado de biblioteca con firma retrasada denominado StringLibrary.dll:

    Importante

    Si usa la línea de comandos en lugar de Visual Studio para crear el ejemplo, debe modificar la llamada al constructor de clase ResourceManager de la siguiente manera: ResourceManager rm = new ResourceManager("Strings", typeof(Example).Assembly);.

    using System;
    using System.Globalization;
    using System.Reflection;
    using System.Resources;
    using System.Threading;
    
    [assembly:NeutralResourcesLanguageAttribute("en")]
    
    public class StringLibrary
    {
       public string GetGreeting()
       {
          ResourceManager rm = new ResourceManager("Strings",
                               Assembly.GetAssembly(typeof(StringLibrary)));
          string greeting = rm.GetString("Greeting");
          return greeting;
       }
    }
    
    Imports System.Globalization
    Imports System.Reflection
    Imports System.Resources
    Imports System.Threading
    
    <Assembly: NeutralResourcesLanguageAttribute("en")>
    
    Public Class StringLibrary
        Public Function GetGreeting() As String
            Dim rm As New ResourceManager("Strings", _
                                          Assembly.GetAssembly(GetType(StringLibrary)))
            Dim greeting As String = rm.GetString("Greeting")
            Return greeting
        End Function
    End Class
    

    El comando para el compilador de C# es el siguiente:

    csc -t:library -resource:Strings.resources -delaysign+ -keyfile:publickey.snk StringLibrary.cs
    

    El comando de compilador de Visual Basic correspondiente es el siguiente:

    vbc -t:library -resource:Strings.resources -delaysign+ -keyfile:publickey.snk StringLibrary.vb
    
  8. Cree un subdirectorio en el directorio principal de la aplicación para cada referencia cultural localizada admitida por la aplicación. Debe crear un subdirectorio en-US, fr-FR y ru-RU. Visual Studio crea estos subdirectorios automáticamente como parte del proceso de compilación. Dado que todos los ensamblados satélite tienen el mismo nombre de archivo, se usan los subdirectorios para almacenar ensamblados satélite individuales específicos de la referencia cultural hasta que se firman con un par de claves pública y privada.

  9. Inserte los archivos .resources individuales específicos de la referencia cultural en ensamblados satélite con firma retrasada y guárdelos en el directorio adecuado. El comando para hacer esto para cada archivo .resources es el siguiente:

    al -target:lib -embed:Strings.culture.resources -culture:culture -out:culture\StringLibrary.resources.dll -delay+ -keyfile:publickey.snk
    

    donde culture es el nombre de una referencia cultural. En este ejemplo, los nombres de referencia cultural son en-US, fr-FR y ru-RU.

  10. Use la herramienta de nombre seguro (sn.exe) de la manera siguiente para volver a firmar StringLibrary.dll:

    sn –R StringLibrary.dll RealKeyPair.snk
    
  11. Vuelva a firmar los ensamblados satélite individuales. Para ello, use la herramienta de nombre seguro (sn.exe) como se indica a continuación para cada ensamblado satélite:

    sn –R StringLibrary.resources.dll RealKeyPair.snk
    
  12. Registre StringLibrary.dll y cada uno de sus ensamblados satélite en la memoria caché global de ensamblados usando el siguiente comando:

    gacutil -i filename
    

    donde filename es el nombre del archivo que se va a registrar.

  13. Si está usando Visual Studio, cree un proyecto de aplicación de consola de nombre Example, agregue una referencia a StringLibrary.dll, y el siguiente código fuente, y compílelo.

    using System;
    using System.Globalization;
    using System.Threading;
    
    public class Example
    {
       public static void Main()
       {
          string[] cultureNames = { "en-GB", "en-US", "fr-FR", "ru-RU" };
          Random rnd = new Random();
          string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
          Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName);
          Console.WriteLine("The current UI culture is {0}",
                            Thread.CurrentThread.CurrentUICulture.Name);
          StringLibrary strLib = new StringLibrary();
          string greeting = strLib.GetGreeting();
          Console.WriteLine(greeting);
       }
    }
    
    Imports System.Globalization
    Imports System.Threading
    
    Module Example
        Public Sub Main()
            Dim cultureNames() As String = {"en-GB", "en-US", "fr-FR", "ru-RU"}
            Dim rnd As New Random()
            Dim cultureName As String = cultureNames(rnd.Next(0, cultureNames.Length))
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName)
            Console.WriteLine("The current UI culture is {0}",
                              Thread.CurrentThread.CurrentUICulture.Name)
            Dim strLib As New StringLibrary()
            Dim greeting As String = strLib.GetGreeting()
            Console.WriteLine(greeting)
        End Sub
    End Module
    

    Para compilar desde la línea de comandos, use el comando siguiente para el compilador de C#:

    csc Example.cs -r:StringLibrary.dll
    

    La línea de comandos para el compilador de Visual Basic es la siguiente:

    vbc Example.vb -r:StringLibrary.dll
    
  14. Ejecute Example.exe.

Vea también