Partilhar via


Criar assemblies satélite para aplicativos .NET

Os arquivos de recursos desempenham um papel central em aplicativos localizados. Eles permitem que um aplicativo exiba cadeias de caracteres, imagens e outros dados no idioma e na cultura do usuário e fornecem dados alternativos se os recursos para o idioma ou a cultura do usuário não estiverem disponíveis. O .NET usa um modelo hub-and-spoke para localizar e recuperar recursos localizados. O hub é o assembly principal que contém o código executável não localizável e os recursos para uma única cultura, que é chamada de cultura neutra ou padrão. A cultura padrão é a cultura de fallback para o aplicativo; ele é usado quando não há recursos localizados disponíveis. Use o NeutralResourcesLanguageAttribute atributo para designar a cultura da cultura padrão do aplicativo. Cada spoke se conecta a um assembly satélite que contém os recursos para uma única cultura localizada, mas não contém nenhum código. Como os assemblies satélite não fazem parte do assembly principal, você pode facilmente atualizar ou substituir recursos que correspondem a uma cultura específica sem substituir o assembly principal para o aplicativo.

Nota

Os recursos da cultura padrão de um aplicativo também podem ser armazenados em um assembly satélite. Para fazer isso, atribua ao NeutralResourcesLanguageAttribute atributo um valor de UltimateResourceFallbackLocation.Satellite.

Nome e localização da montagem satélite

O modelo hub-and-spoke requer que você coloque recursos em locais específicos para que eles possam ser facilmente localizados e usados. Se você não compilar e nomear recursos conforme o esperado, ou se não colocá-los nos locais corretos, o Common Language Runtime não poderá localizá-los e usará os recursos da cultura padrão. O gerenciador de recursos .NET é representado pelo ResourceManager tipo e é usado para acessar automaticamente recursos localizados. O gestor de recursos requer o seguinte:

  • Um único conjunto de satélites deve incluir todos os recursos para uma determinada cultura. Em outras palavras, você deve compilar vários arquivos .txt ou .resx em um único arquivo binário .resources .

  • Deve haver um subdiretório separado no diretório do aplicativo para cada cultura localizada que armazena os recursos dessa cultura. O nome do subdiretório deve ser o mesmo que o nome da cultura. Como alternativa, você pode armazenar seus assemblies satélite no cache de assembly global. Neste caso, o componente de informação de cultura do nome forte da assembleia deve indicar sua cultura. Para obter mais informações, consulte Instalar assemblies satélite no Cache de Assembly Global.

    Nota

    Se seu aplicativo incluir recursos para subculturas, coloque cada subcultura em um subdiretório separado sob o diretório do aplicativo. Não coloque subculturas em subdiretórios sob o diretório da cultura principal.

  • O assembly satélite deve ter o mesmo nome que o aplicativo e deve usar a extensão de nome de arquivo ".resources.dll". Por exemplo, se um aplicativo for nomeado Example.exe, o nome de cada conjunto satélite deve ser Example.resources.dll. O nome do assembly satélite não indica a cultura de seus arquivos de recursos. No entanto, o assembly satélite aparece em um diretório que especifica a cultura.

  • Informações sobre a cultura do conjunto satélite devem ser incluídas nos metadados do conjunto. Para armazenar o nome da cultura nos metadados do assembly satélite, especifique a opção ao usar o /culture Assembly Linker para incorporar recursos no assembly satélite.

A ilustração a seguir mostra uma estrutura de diretório de exemplo e requisitos de local para aplicativos que você não está instalando no cache de assembly global. Os itens com extensões .txt e .resources não serão fornecidos com o aplicativo final. Estes são os arquivos de recursos intermediários usados para criar os assemblies finais de recursos de satélite. Neste exemplo, você pode substituir os arquivos .resx pelos arquivos .txt . Para obter mais informações, consulte Empacotar e implantar recursos.

A imagem a seguir mostra o diretório de montagem satélite:

A satellite assembly directory with localized cultures subdirectories.

Compilar montagens satélite

Use o Resource File Generator (resgen.exe) para compilar arquivos de texto ou arquivos XML (.resx) que contêm recursos para arquivos binários .resources. Em seguida, use o Assembly Linker (al.exe) para compilar arquivos .resources em assemblies satélite. al.exe cria um assembly a partir dos arquivos .resources especificados. Os conjuntos de satélites podem conter apenas recursos; eles não podem conter nenhum código executável.

O comando al.exe a seguir cria um assembly satélite para o aplicativo Example a partir do arquivo de recursos alemão strings.de.resources.

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

O comando al.exe a seguir também cria um assembly satélite para o aplicativo Example a partir do arquivo strings.de.resources. A opção /template faz com que o assembly satélite herde todos os metadados do assembly, exceto suas informações de cultura do assembly pai (Example.dll).

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

A tabela a seguir descreve as opções de al.exe usadas nesses comandos com mais detalhes:

Opção Description
-target:lib Especifica que o assembly satélite é compilado em um arquivo de biblioteca (.dll). Como um assembly satélite não contém código executável e não é o assembly principal de um aplicativo, você deve salvar assemblies satélite como DLLs.
-embed:strings.de.resources Especifica o nome do arquivo de recurso a ser incorporado quando al.exe compila o assembly. Você pode incorporar vários arquivos .resources em um assembly de satélite, mas se estiver seguindo o modelo hub-and-spoke, deverá compilar um assembly de satélite para cada cultura. No entanto, você pode criar arquivos .resources separados para cadeias de caracteres e objetos.
-culture:de Especifica a cultura do recurso a ser compilado. O Common Language Runtime usa essas informações quando procura os recursos para uma cultura especificada. Se você omitir essa opção, al.exe ainda compilará o recurso, mas o tempo de execução não poderá encontrá-lo quando um usuário solicitá-lo.
-out:Example.resources.dll Especifica o nome do arquivo de saída. O nome deve seguir o padrão de nomenclatura baseName.resources., onde baseName é o nome do assembly principal e extension é uma extensão de nome de arquivo válida (como .dll). O tempo de execução não é capaz de determinar a cultura de um assembly satélite com base em seu nome de arquivo de saída; você deve usar a opção /culture para especificá-lo.
-template:Example.dll Especifica um assembly do qual o assembly satélite herdará todos os metadados do assembly, exceto o campo de cultura. Essa opção afeta os assemblies satélite somente se você especificar um assembly que tenha um nome forte.

Para obter uma lista completa das opções disponíveis com al.exe, consulte Assembly Linker (al.exe).

Nota

Pode haver momentos em que você deseja usar a tarefa .NET Core MSBuild para compilar assemblies satélite, mesmo que você esteja visando o .NET Framework. Por exemplo, você pode querer usar a opção determinística do compilador C# para poder comparar assemblies de compilações diferentes. Nesse caso, defina GenerateSatelliteAssembliesForCore como no arquivo .csproj para gerar assemblies satélite usando csc.exe em vez de Al.exe (Assembly Linker).true

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

A tarefa .NET Core MSBuild usa csc.exe em vez de al.exe para gerar assemblies satélite, por padrão. Para obter mais informações, consulte Facilitar a aceitação da geração de montagem de satélite "Core".

Exemplo de montagens de satélite

A seguir está um exemplo simples de "Hello world" que exibe uma caixa de mensagem contendo uma saudação localizada. O exemplo inclui recursos para as culturas inglesa (Estados Unidos), francesa (França) e russa (Rússia), e sua cultura de fallback é o inglês. Para criar o exemplo, faça o seguinte:

  1. Crie um arquivo de recurso chamado Greeting.resx ou Greeting.txt para conter o recurso para a cultura padrão. Armazene uma única cadeia de caracteres chamada HelloString cujo valor é "Hello world!" neste arquivo.

  2. Para indicar que o inglês (en) é a cultura padrão do aplicativo, adicione o seguinte System.Resources.NeutralResourcesLanguageAttribute atributo ao arquivo AssemblyInfo do aplicativo ou ao arquivo de código-fonte principal que será compilado no assembly principal do aplicativo.

    [assembly: NeutralResourcesLanguage("en")]
    
    <Assembly: NeutralResourcesLanguage("en")>
    
  3. Adicione suporte para culturas adicionais (en-US, fr-FRe ru-RU) ao aplicativo da seguinte maneira:

    • Para dar suporte à cultura inglesa (Estados Unidos), crie um arquivo de recurso chamado Greeting.en-US.resx ou Greeting.en-US.txt e armazene nele uma única cadeia de caracteres cujo HelloString valor é "Oi worlden-US!".

    • Para dar suporte à cultura francesa (França), crie um arquivo de recurso chamado Greeting.fr-FR.resx ou Greeting.fr-FR.txt e armazene nele uma única cadeia de caracteres cujo HelloString valor é "Salut tout le fr-FR monde!".

    • Para dar suporte ru-RU à cultura russa (Rússia), crie um arquivo de recurso chamado Greeting.ru-RU.resx ou Greeting.ru-RU.txt e armazene nele uma única cadeia de caracteres cujo HelloString valor é "Всем привет!".

  4. Use resgen.exe para compilar cada texto ou arquivo de recurso XML para um arquivo .resources binário. A saída é um conjunto de arquivos que têm o mesmo nome de arquivo raiz que os arquivos .resx ou .txt , mas uma extensão .resources . Se você criar o exemplo com o Visual Studio, o processo de compilação será tratado automaticamente. Se você não estiver usando o Visual Studio, execute os seguintes comandos para compilar os arquivos .resx em arquivos .resources :

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

    Se seus recursos estiverem em arquivos de texto em vez de arquivos XML, substitua a extensão .resx por .txt.

  5. Compile o seguinte código-fonte junto com os recursos para a cultura padrão no assembly principal do aplicativo:

    Importante

    Se você estiver usando a linha de comando em vez de Visual Studio para criar o exemplo, você deve modificar a chamada para o ResourceManager construtor de classe para o seguinte: 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
    

    Se o aplicativo for chamado Exemplo e você estiver compilando a partir da linha de comando, o comando para o compilador C# é:

    csc Example.cs -res:Greeting.resources
    

    O comando correspondente do compilador do Visual Basic é:

    vbc Example.vb -res:Greeting.resources
    
  6. Crie um subdiretório no diretório principal do aplicativo para cada cultura localizada suportada pelo aplicativo. Você deve criar um subdiretório en-US, fr-FR e ru-RU. O Visual Studio cria esses subdiretórios automaticamente como parte do processo de compilação.

  7. Incorpore os arquivos .resources específicos da cultura individual em assemblies satélite e salve-os no diretório apropriado. O comando para fazer isso para cada arquivo .resources é:

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

    onde cultura é o nome da cultura cujos recursos a montagem satélite contém. Visual Studio lida com esse processo automaticamente.

Em seguida, você pode executar o exemplo. Ele fará aleatoriamente uma das culturas suportadas a cultura atual e exibirá uma saudação localizada.

Instalar assemblies satélite no Cache de Assembly Global

Em vez de instalar assemblies em um subdiretório de aplicativo local, você pode instalá-los no cache de assembly global. Isso é particularmente útil se você tiver bibliotecas de classes e assemblies de recursos de biblioteca de classes que são usados por vários aplicativos.

A instalação de assemblies no cache de assembly global requer que eles tenham nomes fortes. Os assemblies de nome forte são assinados com um par de chaves pública/privada válido. Eles contêm informações de versão que o tempo de execução usa para determinar qual assembly usar para satisfazer uma solicitação de vinculação. Para obter mais informações sobre nomes fortes e controle de versão, consulte Controle de versão de assembly. Para obter mais informações sobre nomes fortes, consulte Assemblies com nomes fortes.

Quando você está desenvolvendo um aplicativo, é improvável que você tenha acesso ao par final de chaves pública/privada. Para instalar um assembly satélite no cache de assembly global e garantir que ele funcione conforme o esperado, você pode usar uma técnica chamada assinatura atrasada. Quando você atrasa a assinatura de um assembly, no momento da compilação você reserva espaço no arquivo para a assinatura de nome forte. A assinatura real é adiada para mais tarde, quando o par final de chaves pública/privada estiver disponível. Para obter mais informações sobre assinatura atrasada, consulte Atrasar a assinatura de um assembly.

Obter a chave pública

Para atrasar a assinatura de um assembly, você deve ter acesso à chave pública. Você pode obter a chave pública real da organização em sua empresa que fará a eventual assinatura ou criar uma chave pública usando a ferramenta Nome forte (sn.exe).

O comando Sn.exe a seguir cria um par de chaves pública/privada de teste. A opção –k especifica que Sn.exe deve criar um novo par de chaves e salvá-lo em um arquivo chamado TestKeyPair.snk.

sn –k TestKeyPair.snk

Você pode extrair a chave pública do arquivo que contém o par de chaves de teste. O comando a seguir extrai a chave pública de TestKeyPair.snk e a salva em PublicKey.snk:

sn –p TestKeyPair.snk PublicKey.snk

Atrasar a assinatura de uma Assembleia

Depois de obter ou criar a chave pública, use o Assembly Linker (al.exe) para compilar o assembly e especificar a assinatura atrasada.

O comando al.exe a seguir cria um assembly satélite de nome forte para o aplicativo StringLibrary a partir do arquivo strings.ja.resources:

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

A opção -delay+ especifica que o Assembly Linker deve atrasar a assinatura do assembly. A opção -keyfile especifica o nome do arquivo de chave que contém a chave pública a ser usada para atrasar a assinatura do assembly.

Voltar a assinar uma Assembleia

Antes de implantar seu aplicativo, você deve assinar novamente o assembly satélite assinado com atraso com o par de chaves real. Você pode fazer isso usando Sn.exe.

O seguinte comando Sn.exe assina StringLibrary.resources.dll com o par de chaves armazenado no arquivo RealKeyPair.snk. A opção –R especifica que um assembly assinado anteriormente ou assinado com atraso deve ser assinado novamente.

sn –R StringLibrary.resources.dll RealKeyPair.snk

Instalar um assembly satélite no cache de assembly global

Quando o tempo de execução procura recursos no processo de fallback de recursos, ele procura primeiro no cache de assembly global. (Para obter mais informações, consulte a seção "Processo de fallback de recursos" de Empacote e implante recursos.) Assim que um assembly satélite é assinado com um nome forte, ele pode ser instalado no cache de assembly global usando a ferramenta Global Assembly Cache (gacutil.exe).

O seguinte comando Gacutil.exe instala StringLibrary.resources.dll* no cache de assembly global:

gacutil -i:StringLibrary.resources.dll

A opção /i especifica que Gacutil.exe deve instalar o assembly especificado no cache de assembly global. Depois que o assembly satélite é instalado no cache, os recursos que ele contém ficam disponíveis para todos os aplicativos projetados para usar o assembly satélite.

Recursos no cache de assembly global: um exemplo

O exemplo a seguir usa um método em uma biblioteca de classes .NET para extrair e retornar uma saudação localizada de um arquivo de recurso. A biblioteca e seus recursos são registrados no cache de assembly global. O exemplo inclui recursos para as culturas inglesa (Estados Unidos), francesa (França), russa (Rússia) e inglesa. O inglês é a cultura padrão; seus recursos são armazenados na assembléia principal. O exemplo inicialmente atrasa a assinatura da biblioteca e seus assemblies satélite com uma chave pública e, em seguida, assina-os novamente com um par de chaves pública/privada. Para criar o exemplo, faça o seguinte:

  1. Se você não estiver usando o Visual Studio, use o seguinte comando Strong Name Tool (Sn.exe) para criar um par de chaves públicas/privadas chamado ResKey.snk:

    sn –k ResKey.snk
    

    Se você estiver usando o Visual Studio, use a guia Assinatura da caixa de diálogo Propriedades do projeto para gerar o arquivo de chave.

  2. Use o seguinte comando Strong Name Tool (Sn.exe) para criar um arquivo de chave pública chamado PublicKey.snk:

    sn –p ResKey.snk PublicKey.snk
    
  3. Crie um arquivo de recurso chamado Strings.resx para conter o recurso para a cultura padrão. Armazene uma única cadeia de caracteres chamada Greeting cujo valor é "Como você faz?" nesse arquivo.

  4. Para indicar que "en" é a cultura padrão do aplicativo, adicione o seguinte System.Resources.NeutralResourcesLanguageAttribute atributo ao arquivo AssemblyInfo do aplicativo ou ao arquivo de código-fonte principal que será compilado no assembly principal do aplicativo:

    [assembly:NeutralResourcesLanguageAttribute("en")]
    
    <Assembly: NeutralResourcesLanguageAttribute("en")>
    
  5. Adicione suporte para culturas adicionais (as culturas en-US, fr-FR e ru-RU) ao aplicativo da seguinte maneira:

    • Para suportar a cultura "en-US" ou Inglês (Estados Unidos), crie um arquivo de recurso chamado Strings.en-US.resx ou Strings.en-US.txt e armazene nele uma única cadeia de caracteres cujo Greeting valor é "Olá!".

    • Para suportar a cultura "fr-FR" ou francesa (França), crie um arquivo de recurso chamado Strings.fr-FR.resx ou Strings.fr-FR.txt e armazene nele uma única cadeia de caracteres cujo Greeting valor é "Bon jour!".

    • Para suportar a cultura "ru-RU" ou russo (Rússia), crie um arquivo de recurso chamado Strings.ru-RU.resx ou Strings.ru-RU.txt e armazene nele uma única cadeia de caracteres cujo Greeting valor é "Привет!".

  6. Use resgen.exe para compilar cada texto ou arquivo de recurso XML para um arquivo .resources binário. A saída é um conjunto de arquivos que têm o mesmo nome de arquivo raiz que os arquivos .resx ou .txt , mas uma extensão .resources . Se você criar o exemplo com o Visual Studio, o processo de compilação será tratado automaticamente. Se você não estiver usando o Visual Studio, execute o seguinte comando para compilar os arquivos .resx em arquivos .resources :

    resgen filename
    

    Onde filename é o caminho opcional, o nome do arquivo e a extensão do arquivo .resx ou de texto.

  7. Compile o seguinte código-fonte para StringLibrary.vb ou StringLibrary.cs juntamente com os recursos para a cultura padrão em um assembly de biblioteca assinado com atraso chamado StringLibrary.dll:

    Importante

    Se você estiver usando a linha de comando em vez de Visual Studio para criar o exemplo, você deve modificar a chamada para o ResourceManager construtor de classe para 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
    

    O comando para o compilador C# é:

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

    O comando correspondente do compilador do Visual Basic é:

    vbc -t:library -resource:Strings.resources -delaysign+ -keyfile:publickey.snk StringLibrary.vb
    
  8. Crie um subdiretório no diretório principal do aplicativo para cada cultura localizada suportada pelo aplicativo. Você deve criar um subdiretório en-US, fr-FR e ru-RU. O Visual Studio cria esses subdiretórios automaticamente como parte do processo de compilação. Como todos os assemblies satélite têm o mesmo nome de arquivo, os subdiretórios são usados para armazenar assemblies satélites específicos de cultura individual até que sejam assinados com um par de chaves pública/privada.

  9. Incorpore os arquivos .resources específicos da cultura individual em assemblies satélite assinados com atraso e salve-os no diretório apropriado. O comando para fazer isso para cada arquivo .resources é:

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

    onde cultura é o nome de uma cultura. Neste exemplo, os nomes de cultura são en-US, fr-FR e ru-RU.

  10. Assine novamente StringLibrary.dll usando a ferramenta Nome forte (sn.exe) da seguinte maneira:

    sn –R StringLibrary.dll RealKeyPair.snk
    
  11. Assine novamente os conjuntos de satélites individuais. Para fazer isso, use a ferramenta Nome forte (sn.exe) da seguinte maneira para cada conjunto de satélite:

    sn –R StringLibrary.resources.dll RealKeyPair.snk
    
  12. Registre StringLibrary.dll e cada um de seus assemblies satélite no cache de assembly global usando o seguinte comando:

    gacutil -i filename
    

    onde filename é o nome do arquivo a ser registrado.

  13. Se você estiver usando o Visual Studio, crie um novo projeto de Aplicativo de Console chamado Example, adicione uma referência a StringLibrary.dll e o seguinte código-fonte a ele e compile.

    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 a partir da linha de comando, use o seguinte comando para o compilador C#:

    csc Example.cs -r:StringLibrary.dll
    

    A linha de comando para o compilador do Visual Basic é:

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

Consulte também