2010-03-20 10 views
15

Abbiamo avuto un problema molto interessante con un progetto Win Forms. È stato risolto Sappiamo cosa è successo, ma vogliamo capire perché è successo. Ciò potrebbe aiutare altre persone in futuro a risolvere un problema simile.Riferimento .NET "Copia locale" Vero/Falso impostato in base al contenuto di GAC

Il progetto WinForms non è riuscito su 2 PC dei nostri clienti. L'errore era un errore kernel.dll oscuro. Il progetto è andato bene su altri 3 PC.

Abbiamo trovato che una DLL (log4net.dll - una libreria di registrazione open source molto popolare) mancava dalla nostra cartella di rilascio. Era precedentemente nella nostra cartella di rilascio. Perché mancava in questa ultima versione?

Mancava perché è stato installato un programma nella mia casella Dev che utilizzava log4net.dll ed è stato aggiunto alla Global Assembly Cache.

Quando ho controllato i riferimenti della soluzione per log4net.dll, sono stati modificati in "copia local = FALSE". Devono essere cambiati automaticamente perché log4net.dll era presente nel mio GAC.

Ecco dove inizia la mia domanda:

Perché il mio riferimento per log4net.dll ottenere cambiato dalla copia locale = TRUE per copia locale = FALSE? Sospetto che sia stato aggiunto al mio GAC da un altro programma.

Come possiamo evitare che ciò accada di nuovo? Allo stato attuale, se installo un software che utilizza una libreria comune e lo aggiunge al mio GAC, i miei SLN che fanno riferimento a tale DLL cambieranno da Copia locale TRUE a FALSE.

+0

Qual è l'Assemblea Generale? http://en.wikipedia.org/wiki/Global_Assembly_Cache? –

risposta

6

Ciò è accaduto perché non ha alcun senso avere Copia Local = True se un assembly è installato nel GAC. Poiché quella copia locale non verrà mai utilizzata, la ricerca GAC ​​viene sempre eseguita per prima. Lasciandolo invariato causerebbe una grande confusione, si potrebbe pensare che si sta utilizzando la copia locale, ma ottenere un altro. Cambiarlo provoca anche una confusione, se non lo si nota, che potrebbe essere stato risolto con una finestra di messaggio al momento del caricamento della soluzione.

Log4net è un troublemaker, ci sono troppe versioni in circolazione senza alcuna procedura di distribuzione che assicura che quelle versioni non si mordono a vicenda. Qualcosa a cui apparentemente Apache non voleva rivolgersi, lasciandolo invece al programmatore. Avere prodotti che dipendono da Log4net e fare qualcosa riguardo al rischio di Hell Hell percepito è in qualche modo inevitabile. In cambio di darti un problema con l'Hell DLL.

Nessuna risposta semplice e pulita, oltre a sapere cosa è installato sul computer. Prendere in considerazione la possibilità di postare su connect.microsoft.com per chiedere un avviso quando Visual Studio aggiorna automaticamente la proprietà Copia locale. È una domanda ragionevole.

+0

Da nobugz: "Considerare la pubblicazione su connect.microsoft.com per chiedere un avviso quando Visual Studio aggiorna automaticamente la proprietà Copia locale." Grazie, bugz. Questa è una grande idea. Una notifica quando le modifiche "copia locale" sarebbero grandiose. Questo è VS2K5, btw. Mi ricorda la maneggevolezza del markup magico di VS2K3. Grazie anche per l'intuizione. –

+0

Vero e +1, anche se non darei la colpa interamente ad Apache (o Neoworks, l'autore originale) - dubito che abbiano previsto quanto sarebbero diventate diffuse le distribuzioni ad hoc. * La maggior parte dei * prodotti open source non sono così arroganti da cercare di infiltrarsi nel vostro GAC, e se Apache avesse cambiato il modello ora, avrebbe infranto il codice esistente (come è stato dimostrato qui). – Aaronaught

+0

Un modo per impedirne la modifica? Sospetto che "Questo è di progettazione". Se questo è vero, allora ho bisogno di controllare i ref periodicamente se la mia dev/build box è il mio PC principale e aggiungo/rimuovo cose frequentemente? –

0

Puoi assicurarti che il tuo venga aggiunto aggiungendo un file hintpath al file msbuild/proj?

Dal link sopra:

HintPath: relativo o assoluto percorso dell'assieme.

2

In fase di esecuzione, gli assembly devono trovarsi in una delle due posizioni: il percorso di output del progetto o la cache di assembly globale (consultare Operazioni con gli assembly e la cache degli assembly globali).Se il progetto contiene un riferimento a un oggetto che non si trova in una di queste posizioni, quando il progetto viene creato, il riferimento deve essere copiato nel percorso di output del progetto. La proprietà CopyLocal indica se è necessario eseguire questa copia. Se il valore è true, il riferimento viene copiato. Se falso, il riferimento non viene copiato.

Il valore progetto assegnato dal CopyLocal è determinato nel seguente ordine:

  1. Se il riferimento è un altro progetto, chiamato un riferimento di progetto a progetto, allora il valore è vero.
  2. Se l'assembly si trova nella cache di assembly globale, il valore è falso.
  3. Come caso speciale, il valore per il riferimento mscorlib.dll è falso.
  4. Se l'assembly viene trovato nella cartella SDK Framework, il valore è falso. Altrimenti, il valore è true.

Saluti ... Muse VSExtensions

1

Ho appena incontrato questo problema sui nostri server di build troppo. Questo è un comportamento molto fastidioso (e inaspettato) di Visual Studio. Due soluzioni alternative:

  1. Rimuovere i gruppi dal GAC.
  2. Aggiungere un evento PostBuild per copiare manualmente gli assembly nella directory di output.
1

Ho trovato una soluzione per noi sui nostri server di compilazione.

Problema: In una data specifica senza motivo (ora presumo che il file sia stato aggiunto al GAC) l'assembly System.Web.MVC.dll è scomparso da molti dei nostri progetti. Sono sicuro che questo si applica a qualsiasi DLL con il problema.

Soluzione: In Visual Studio modificare il riferimento (assumendo Copia locale è già True).

  1. Modifica copia locale = True alla copia locale = False
  2. Modifica copia locale Torna a True
  3. Avviso nel Csproj presentare una <Private>True</Private> viene aggiunto.
  4. Compila ora e vedrai che la dll viene effettivamente inclusa anche se il messaggio rimane lo stesso.

Soluzione2: Aggiungere manualmente la proprietà <private>True</private>.

Conclusioni: La mia comprensione di <Private> è la copia locale, quindi se Copia Locale = Vero è necessario aggiungere la proprietà privata, ma nel nostro caso almeno non lo era.

Considerazioni aggiuntive:

  1. Testato utilizzando Visual Studio 2013 e il 2015.
  2. testata utilizzando msbuild 12 e 14.
  3. testati utilizzando TFS costruire Template.
  4. Il nostro codice è stato aggiornato dal 2008 al 2015 in studio visivo, la bandiera potrebbe essere incasinata da qualche parte in quel momento, ma il problema non è stato avviato fino a quando l'assembly non è stato aggiunto al GAC in qualche modo.

Risultato finale:

<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral,PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 
<SpecificVersion>False</SpecificVersion> 
<HintPath>packages\Microsoft.AspNet.Mvc.4.0.40804.0\lib\net40\System.Web.Mvc.dll  </HintPath> 
     <Private>True</Private> 
    </Reference> 
Problemi correlati