Technology Experience

Contenuti gestiti da Igor Damiani
posts - 949, comments - 2741, trackbacks - 15120

My Links

News

  • Questo blog si propone di raccogliere riflessioni, teoriche e pratiche, su tutto quello che riguarda il world-computing che mi sta attorno: programmazione in .NET, software attuale e futuro, notizie provenienti dal web, tecnologia in generale, open-source.

    L'idea è quella di lasciare una sorta di patrimonio personale, una raccolta di idee che un giorno potrebbe farmi sorridere, al pensiero di dov'ero e cosa stavo facendo.

    10/05/2005,
    Milano

Archives

Post Categories

Generale

[MCAD.34] Global Assembly Cache, gacutil.exe e dintorni

Più di una volta avrete sentito della famigerata Global Assembly Cache, per gli amici GAC. Di cosa si tratta? La GAC è una sorta di raccoglitore di tutti gli assembly che noi vogliamo condividere tra più di un'applicazione. Lo scopo della GAC è proprio questo: se noi sviluppiamo un assembly DLL contenente classi che noi vogliamo utilizzare in diverse applicazioni .NET, possiamo semplicemente installare questo assembly nella GAC e il gioco è fatto. Per poter installare un assembly nella GAC, occorre innanzittutto firmarlo con uno strong name , quindi utilizzare il tool sn.exe e decorare l'assembly con l'attributo AssemblyKeyFile, come abbiamo fatto precedentemente. Se un assembly utilizza a sua volta un altro assembly, anche quest'ultimo deve avere uno strong name, altrimenti...nisba!

Perchè è obbligatorio firmare con lo strong name? Avevo già detto che i motivi per cui viene usato uno strong name sono essenzialmente due: versioning e authentication. In questo caso, lo strong name serve proprio per il versioning. Ricordiamoci infatti che quando un assembly viene firmato con uno strong name, il suo identifier diventa univoco. Se è univoco, può entrare nella GAC senza problemi.

Diamo un'occhiata alla GAC del nostro PC
Se avete installato il .NET Framework sul vostro PC, provate a dare un'occhiata alla directory C:\Winnt\Assembly vedrete l'elenco degli assembly contenuti nella vostra GAC. Nella maggior parte dei casi, sarà l'elenco predefinito creato dal setup del framework.

La cosa in realtà non è così semplice. In effetti, Windows utilizza il file Shfusion.dll che è una shell extension. A cosa serve? Semplice: in realtà la struttura della GAC è un po' più complessa di quella che Windows vi fa vedere attraverso il classico Windows Explorer. Provate ad aprire una command line, navigate fino a C:\Winnt\Assembly a suon di cd e vedrete di cosa sto parlando.
In altre parole, il framework è in grado di mantenere nella GAC più versioni di un certo assembly . Le versioni possono variare per Culture, per Version (appunto), eccetera. Dal momento che abbiamo a disposizione più di una versione di ogni componente, possiamo ad esempio dire che la nostra applicazione Age deve usare un certo assembly ad una certa release.

Lo scopo? Risolvere un bel pasticcio!
Qual'è lo scopo di tutto questo? Avete mai sentito parlare di 'DLL Hell' ?
Lasciatemi descrivere un tipico scenario pre era-.NET.
La mia applicazione PrintOrders utilizza il componente PrintPreview.dll alla versione X.Y.Z per gestire l'anteprima di stampa. PrintPreview.dll è un file DLL condiviso, magari messo in C:\Windows\System32. Tutto fila liscio, fino a quando un altro programma aggiorna questa DLL, installando una nuova versione con un object model un po' diverso. Ecco tutto ad un tratto PrintOrders che comincia a dare errori da tutte le parti, perchè la nuova release di PrintPreview.dll causa qualche conflitto non si sa bene dove e perchè.
Questo perchè prima dell'avvento di .NET Windows aveva una sola copia di ciascun componente (per renderla semplice): se una DLL veniva aggiornata, tutte le applicazioni che usavano quella DLL potevano potenzialmente subire qualche tipo di malfunzionamento.

Oggi invece abbiamo il .NET Framework. Oggi noi possiamo creare un assembly PrintPreview.dll ed installarlo nella GAC. Possiamo avere a disposizione tutte le versioni di questo assembly eventualmente installate. Quindi, possiamo forzare la nostra applicazione dicendo che deve obbligatoriamente usare PrintPreview.dll ad una certa versione.

Questo è lo scopo della Global Assembly Cache. Attraverso la command-line è possibile vedere la vera struttura della GAC, composta di una serie di directory per ogni assembly. Se siete in C:\Winnt\Assembly, provate a dare ad esempio il seguente comando:

cd System.Drawing

Questa directory contiene tutta una serie di directory che permettono al framework di gestire la situazione senza troppi problemi. Come possiamo aggiungere un nostro assembly alla GAC?

Installare un assembly nella GAC
Come abbiamo detto prima, dobbiamo averlo firmato con uno strong name. Poi possiamo aggiungerlo alla GAC in tre modi diversi, più o meno complessi:

  1. Facendo un bel drag'n'drop del nostro assembly dalla directory dentro C:\Winnt\Assembly
  2. Facendolo installare da un setup di qualche tipo
  3. Usando l'utility gacutil.exe

Siccome vogliamo diventare MCAD, sapere almeno la sintassi del comando gacutil.exe può essere utile, giusto? Beh, allora, vediamola!!!

Usare gacutil.exe per gestire la Global Assembly Cache
Andiamo a vedere velocemente alcune tipiche sintassi del comando gacutil.exe.

gacutil /i C:\Progetto\ReadRegistry.exe
Installa l'assembly nella GAC. Per disinstallare usare l'opzione /u .

gacutil /il ElencoAssembly.txt
Installa gli assembly specificati nel file di testo. Il file di testo deve contenere informazioni formattate così:

myAssembly1,Version=1.1.0.0,Culture=en,PublicKeyToken=874e23ab874e23ab
myAssembly2,Version=1.1.0.0,Culture=en,PublicKeyToken=874e23ab874e23ab
myAssembly3,Version=1.1.0.0,Culture=en,PublicKeyToken=874e23ab874e23ab

Quello indicato, notare, è il nome univoco di un assembly, ottenuto grazie allo strong name. Per disinstallare, usare l'opzione /ul.

Quando è opportuno usare gacutil.exe ?
Come succedeva con i buoni vecchi componenti COM di una volta, il framework tiene traccia di un reference counter, ovvero, banalmente, di quante volte un certo assembly è referenziato da altri assembly o applicazioni. Questo per evitare di rimuovere un assembly dalla GAC se questo in realtà serve a qualcun altro. Per default, gacutil non incrementa questo reference counter: diverse pagine che ho letto su MSDN dicono di non usare gacutil in produzione, ma solo durante lo sviluppo dell'applicazione.

Non è proprio vero. Utilizzando l'opzione /r di gacutil, possiamo comunque fare in modo di incrementare il reference di un'unità. Però la regola rimane valida: quando si deve distribuire un assembly, è più logico e plausibile utilizzare un installer, che è anche più comodo per l'utente finale.

powered by IMHO 1.2

Print | posted on martedì 20 settembre 2005 18:08 | Filed Under [ MCAD ]

Feedback

Gravatar

# re: [MCAD.34] Global Assembly Cache, gacutil.exe e dintorni

Ma nel config della tua applicazione puoi precisare la versione dell' assembly da usare. Ricordati che la app va prima a guardare nella cartella bin, poi cerca l' assembly nella GAC.
15/05/2006 12:35 | Raffaeu
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET