A reutilização de código representa, sem sombra de dúvidas, uma das grandes preocupações dentro da área de desenvolvimento de software. O reaproveitamento de funcionalidades já implementadas carrega consigo benefícios óbvios, como uma maior agilidade na construção de novas soluções ou, até mesmo, a possibilidade de se evitar a duplicação de código (e consequentemente, dificultar atividades futuras de manutenção de aplicações).

Tomando por base o desenvolvimento voltado à plataforma Windows, a criação de DLLs (sigla de “Dynamic-link library”) é considerada uma das principais maneiras de se viabilizar o reuso de funções elaboradas anteriormente. Mediante a instalação prévia ou ainda, através do registro de tais recursos em algum tipo de repositório, arquivos .dll podem ser utilizados por várias aplicações simultaneamente.

Antes do surgimento do .NET Framework, o uso de dlls contendo recursos para a construção de novos sistemas estava normalmente associado à tecnologia COM. O padrão COM (sigla do inglês “Component Object Model” é de autoria da própria Microsoft, tendo por objetivo principal oferecer alternativas para a interoperabilidade entre sistemas. Esta meta é cumprida através de um processo de instalação de DLLs em computadores com o sistema operacional Windows, possibilitando com isso que aplicações implantadas posteriormente em tais máquinas consigam consumir bibliotecas registradas nas mesmas.

Por mais que o padrão COM tenha representado um avanço ao estimular práticas como a componentização, diversos problemas surgiriam decorrentes da adoção deste modelo. Muitas destas dificuldades giravam em torno de erros ocasionados pela instalação de diferentes versões de uma DLL em um mesmo computador. A cada atualização uma biblioteca poderia vir a ser registrada novamente, substituindo assim outra versão pré-existente (mais recente ou não); com isto, aplicações já em uso teriam sua operação normal comprometida, com uma série de erros prejudicando a atuação de usuários em atividades do dia-a-dia. Este tipo de situação era tão recorrente entre desenvolvedores de sistemas em Visual Basic (e até em Delphi) que ficou conhecido como “DLL Hell” (ou “inferno das DLLs”, em uma tradução livre).

Mesmo quando a tecnologia COM não é empregada, outras questões envolvendo o uso de DLLs também devem ser levadas em conta. Um tipo de problema bastante comum neste último caso é a existência de inúmeras versões para uma biblioteca num mesmo computador, com cada uma destas representando partes de diferentes aplicações. Se uma DLL for alterada de forma a se corrigir um erro no futuro, existe a probabilidade do esquecimento em se proceder com a atualização de tal biblioteca para um ou mais sistemas.

Desde sua primeira versão o .NET conta com um mecanismo que procura sanar as dificuldades aqui mencionadas. Trata-se do Global Assembly Cache ou, simplesmente, GAC:

http://msdn.microsoft.com/en-us/library/yf1d93sz(v=vs.110).aspx

O objetivo deste artigo é fornecer uma visão geral a respeito do funcionamento do Global Assembly Cache e ainda, de que maneira o mesmo pode simplificar o gerenciamento de bibliotecas utilizadas por diferentes aplicações .NET em um mesmo computador.

Como funciona o Global Assembly Cache?

O Global Assembly Cache nada mais é do que um repositório centralizado para o armazenamento de assemblies (DLLs) gerados em .NET. Cada versão do .NET Framework conta com um repositório próprio. Partindo desta premissa, toda vez que um assembly tenha sido adicionado ao GAC, o mesmo estará disponível para uso por qualquer aplicação .NET compatível com a versão da biblioteca adicionada ao repositório.

Estas características permitem que a plataforma .NET supere os problemas característicos do “DLL Hell”, além de oferecer um mecanismo centralizado para a utilização de bibliotecas de uso geral (sem que isto implique em múltiplas cópias de DLLs, as quais estariam espalhadas ao longo de vários projetos).

A biblioteca a ser registrada no GAC precisará, obrigatoriamente, contar com uma assinatura digital. Este tipo de ação aumenta a segurança no acesso a um assembly, uma vez que bibliotecas que passaram por este tipo de procedimento terão informações básicas como o seu número de versão e outros detalhes de configuração criptografados.

Com isto se cria uma identificação única para o assembly, além de possibilitar uma proteção adicional a aplicações que dependam do mesmo: o processo de se gerar a assinatura de um assembly procura garantir a integridade de uma biblioteca, evitando assim os efeitos colaterais de bibliotecas modificadas por vírus e outros tipos de programas maliciosos.

No caso específico do Visual Studio 2012, a assinatura de um assembly é normalmente criada acessando-se a seção “Signing”, na janela “Properties” de um projeto. A Figura 1 apresenta um exemplo disto:

Gerando a assinatura de uma biblioteca no Visual Studio 2012

Figura 1: Gerando a assinatura de uma biblioteca no Visual Studio 2012

Maiores informações sobre como gerar uma assinatura para um assembly podem ser obtidas através do link:

http://msdn.microsoft.com/en-us/library/xc31ft41.aspx

Uma recomendação importante precisa ser feita no que se refere ao GAC e a geração de assemblies com assinatura. Caso não existam ameaças significativas à segurança (por se tratar de um ambiente controlado) e, além disso, não se verifique a possibilidade de uma biblioteca ser compartilhada entre várias aplicações, não haverá a necessidade de se proceder com o registro da DLL correspondente no Global Assembly Cache.

Registrando uma biblioteca no Global Assembly Cache

A instalação de um assembly no Global Assembly Cache pode ser efetuada das seguintes formas:

  • Usando um instalador, que se encarrega de registrar uma ou mais bibliotecas junto ao GAC. O próprio Visual Studio conta com templates para a geração de projetos de instalação;
  • Utilizando uma ferramenta de desenvolvimento conhecida como Global Assembly Cache Tool (ou simplesmente “gacutil.exe”), a qual faz parte do SDK do .NET Framework.

Por default, o utilitário gacutil.exe existe apenas em ambiente de desenvolvimento, ou seja, o mesmo deverá estar presente em máquinas nas quais foi instalada uma versão do Visual Studio. No caso da versão 2012 desta IDE, o executável gacutil.exe pode ser encontrado em:

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\

O registro de assemblies a partir do executável gacutil.exe pode ser demonstrado através de um exemplo bastante simples. Isto será feito por meio de um teste que visa à inclusão dos arquivos que compõem o framework conhecido como NPOI no GAC.

A biblioteca NPOI (atualmente na versão 2.0 beta 1 – Julho/2013) permite a realização de operações de leitura/escrita em planilhas do Excel, sem que isto represente a obrigatoriedade de se instalar recursos que compõem o pacote Office em um computador. Um exemplo de utilização deste conjunto de funcionalidades pode ser visualizado através do link:

//www.devmedia.com.br/excel-x-net-framework-gerando-planilhas-xls-sem-o-uso-de-interop-com/27784

É importante destacar que o framework NPOI não conta com um instalador próprio. Logo, se houver a necessidade de registrá-lo junto ao Global Assembly Cache a fim de viabilizar o uso do mesmo por diversas aplicações, será preciso se proceder com a criação de um instalador ou empregar diretamente o utilitário gacutil.exe, conforme mencionado anteriormente.

O primeiro passo no sentido de registrar o NPOI junto ao GAC consiste no download dos arquivos que compõem esta biblioteca. Para isto, acessar o link indicado a seguir, baixando a partir do mesmo a versão 2.0 do framework:

http://npoi.codeplex.com/release

Em seguida, descompactar o conteúdo do arquivo baixado em uma pasta (Figura 2) do computador no qual o framework NPOI será instalado.

DLLs que compõem o NPOI

Figura 2: DLLs que compõem o NPOI

Acessar agora como Administrador o prompt de comandos do Visual Studio 2012 (clicando com o botão direito do mouse sobre a opção correspondente): Menu Iniciar > Microsoft Visual Studio 2012 > Visual Studio Tools > Developer Command Prompt for VS2012.

Dentro do prompt do Visual Studio, navegar até o diretório em que se encontram as bibliotecas do NPOI para o .NET Framework 4.0/4.5 (Figura 3).

Prompt de comandos do Visual Studio 2012

Figura 3: Prompt de comandos do Visual Studio 2012

Registrar então as DLLS, acionando o executável gacutil.exe para cada um dos diferentes arquivos presentes no diretório já citado. Conforme especificado a seguir, informar a opção “/i” como parâmetro, seguida pelo nome de cada biblioteca:

  • gacutil /i NPOI.dll
  • gacutil /i ICSharpCode.SharpZipLib.dll
  • gacutil /i NPOI.OOXML.dll
  • gacutil /i NPOI.OpenXml4Net.dll
  • gacutil /i NPOI.OpenXmlFormats.dll

A cada linha de comando executada, o gacutil.exe emitirá uma mensagem indicando o resultado da ação (Figura 4).

Executando o utilitário gacutil.exe

Figura 4: Executando o utilitário gacutil.exe

Acessando o diretório C:\Windows\assembly\ (em um computador com o Windows 7 instalado) será possível constatar que as bibliotecas do NPOI foram implantadas com sucesso, como indicado nas Figuras 5 e 6.

Bibliotecas do NPOI registradas com sucesso no GAC

Figura 5: Bibliotecas do NPOI registradas com sucesso no GAC

Biblioteca da qual o NPOI depende registrada no GAC

Figura 6: Biblioteca da qual o NPOI depende registrada no GAC

Qualquer aplicação que utilize o NPOI poderá agora ser implantada no computador em que este framework foi registrado, sem que os arquivos que compõem o mesmo precisem constar em algum diretório específico de tal solução.

Observação: por mais que o gacutil.exe seja instalado por default apenas em computadores de desenvolvimento, é possível copiar este utilitário (juntamente com o arquivo gacutil.exe.config) para máquinas que não dispõem do Visual Studio, possibilitando assim o registro de assemblies gerados em .NET via linha de comando.

Conclusão

Conforme discutido ao longo deste artigo, o Global Assembly Cache (GAC) oferece um repositório centralizado para o gerenciamento de bibliotecas .NET, sem incorrer em problemas que eram tão comuns à tecnologia COM. Além disso, outro benefício direto deste mecanismo é evitar a necessidade de se manterem múltiplas cópias de assemblies, os quais seriam comuns a diversas aplicações em um mesmo computador.

Isto não significa, entretanto, que tudo o que for desenvolvido em .NET deva ser registrado no GAC. Geralmente, funcionalidades de cunho geral e com possibilidade de reuso representam candidatas potenciais para este tipo de ação.

Espero que o conteúdo aqui apresentado possa ser útil no seu dia-a-dia.

Até uma próxima oportunidade!