Risoluzione dell'MSB3247 - Sono stati rilevati conflitti tra versioni diverse dello stesso assembly dipendente


427

Una soluzione .NET 3.5 è finita con questo avviso durante la compilazione con msbuild.

A volte NDepend potrebbe essere d'aiuto, ma in questo caso non ha fornito ulteriori dettagli. Come Bob, ho dovuto ricorrere all'apertura di ogni assembly in ILDASM fino a quando non ho trovato quello che faceva riferimento a una versione precedente dell'assembly dipendente.

Ho provato ad usare MSBUILD da VS 2010 Beta 2 (come l'articolo di Connect indicava che era stato corretto nella prossima versione del CLR) ma che non forniva ulteriori dettagli (forse post fisso Beta 2)

Esiste un approccio migliore (più automatizzato)?


2
Nel mio caso, dovevo solo assicurarmi che tutti i progetti nella soluzione avessero la stessa versione dei pacchetti nuget (posso semplicemente aggiornare tutti all'ultimo).
Michael,

Risposte:


576

Modificare il "livello di dettaglio dell'output di compilazione del progetto MSBuild" su "Dettagliato" o superiore. Per fare ciò, attenersi alla seguente procedura:

  1. Visualizza la finestra di dialogo Opzioni ( Strumenti -> Opzioni ... ).
  2. Nella struttura a sinistra, selezionare il nodo Progetti e soluzioni , quindi selezionare Crea ed esegui .
    • Nota: se questo nodo non viene visualizzato, assicurarsi che la casella di controllo nella parte inferiore della finestra di dialogo Mostra tutte le impostazioni sia selezionata.
  3. Nella pagina strumenti / opzioni che appare, imposta il livello di verbosità dell'output di compilazione del progetto MSBuild sull'impostazione appropriata a seconda della versione:

  4. Costruisci il progetto e guarda nella finestra di output.

Dai un'occhiata ai messaggi di MSBuild. L' ResolveAssemblyReferencesattività, che è l'attività da cui proviene MSB3247, dovrebbe aiutarti a eseguire il debug di questo particolare problema.

Il mio caso specifico era un riferimento errato a SqlServerCe. Vedi sotto. Ho avuto due progetti che fanno riferimento a due diverse versioni di SqlServerCe. Sono andato al progetto con la versione precedente, rimosso il riferimento, quindi aggiunto il riferimento corretto.

Target ResolveAssemblyReferences:
    Consider app.config remapping of assembly "System.Data.SqlServerCe, ..." 
        from Version "3.5.1.0" [H:\...\Debug\System.Data.SqlServerCe.dll] 
        to Version "9.0.242.0" [C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PublicAssemblies\System.Data.SqlServerCe.dll]
        to solve conflict and get rid of warning.
    C:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets : 
        warning MSB3247: Found conflicts between different versions of the same dependent assembly.

Non è necessario aprire ciascun assieme per determinare le versioni degli assiemi di riferimento.

  • È possibile controllare le proprietà di ciascun riferimento.
  • Apri le proprietà del progetto e controlla le versioni della sezione Riferimenti.
  • Apri i progetti con un editor di testo.
  • Utilizzare .Net Reflector.

5
Le tue soluzioni mi sembrano buone, tuttavia non penso che sia sempre utile utilizzare la sezione Riferimenti per visualizzare i numeri di versione. Ho spesso visto VS "mentire" su quale versione sta usando rispetto a quale versione è effettivamente menzionata nel file .csproj.
David Gardiner,

5
@David Gardiner - Concordo con la tua affermazione "bugiarda" quando usi i progetti C #. Nella mia esperienza, i progetti C # possono confondersi per quanto riguarda la versione referenziata e la versione effettiva compilata / collegata. Quando ciò accade, pulisco la soluzione, elimino manualmente le cartelle bin e obj, quindi elimino gli assembly di progetto temporanei in% APPDATA%. Una soluzione di ricostruzione di solito risolve il problema. (VB raramente soffre di questo problema specifico.)
AMissico,

54
vincere per dire alle persone di usare effettivamente la finestra Output. Build è molto più della finestra Elenco errori F5 +.
JJS

2
Come ErikHeemskerk ha menzionato nella sua risposta, in Visual Studio 2010 dovrai impostare la verbosità dell'output su dettagliata per vedere l'output di ResolveAssemblyReferences.
Robin Clowers,

12
Suggerimento: per trovare il punto esatto nell'output dettagliato della build, copiare il testo in un editor di testo, cercare "Conflitti trovati tra versioni diverse dello stesso assembly dipendente".
Contango,

133

Mike Hadlow ha pubblicato una piccola app console chiamata AsmSpy che elenca piuttosto bene i riferimenti di ogni assembly:

Reference: System.Net.Http.Formatting
        4.0.0.0 by Shared.MessageStack
        4.0.0.0 by System.Web.Http

Reference: System.Net.Http
        2.0.0.0 by Shared.MessageStack
        2.0.0.0 by System.Net.Http.Formatting
        4.0.0.0 by System.Net.Http.WebRequest
        2.0.0.0 by System.Web.Http.Common
        2.0.0.0 by System.Web.Http
        2.0.0.0 by System.Web.Http.WebHost

Questo è un modo molto più veloce per arrivare in fondo all'avviso MSB3247, piuttosto che dipendere dall'output di MSBuild.


1
AsmSpy è fantastico, devi solo ricordare che stai cercando i riferimenti a DLL di terze parti con versioni non corrispondenti. Generalmente, le versioni non corrispondenti nei riferimenti alle librerie standard non causeranno questi avvisi (e li vedrai molto).
Tod Thomson,

Questo è un ottimo piccolo strumento che mi ha aiutato a risolvere immediatamente il mio problema. Nel mio caso, tuttavia, non si trattava esattamente di DLL di terze parti, ma piuttosto di riferimenti a System.Management.Automation.dll che avevano riferimenti diversi a mscorlib.dll.
Chris Gillum,

Lo strumento è carino, tuttavia, non funziona in tutte le circostanze. Almeno per un progetto .NET 4.5 non ha mostrato le versioni dei riferimenti in conflitto per me. + L'output di msbuild nomina le DLL in questione con i percorsi e tutti.
tw

11
Grazie per le belle parole ragazzi :)
Mike Hadlow,

Mi hai appena salvato qualche ora di lavoro! Ha aiutato a leggere l'output dettagliato, ma una volta fatto è stato facile verificare nuovamente con il tuo strumento.
Norman H,

22

Qualche volta la risposta di @AMissico non è abbastanza. Nel mio caso, non sono riuscito a trovare l'errore nelle finestre di output, quindi ho deciso di creare un file di registro e analizzarlo, procedendo come segue:

  1. Salvataggio del registro di build in un file ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

    msbuild MyProject.proj /fl /flp:logfile=MyProjectOutput.log;verbosity=detailed

  2. Trova il testo: warning MS...o le informazioni specifiche di avviso: (ad esempio la riga 9293) Found conflicts between different versions...e tutti i dettagli dell'errore di conflitto saranno sopra questo messaggio (ad esempio la riga 9277)There was a conflicts between... Trova il messaggio di errore

Visual Studio 2013


Ottimo suggerimento per cercare 3277 nell'output.
sfuqua,

21

Ho scoperto che (almeno in Visual Studio 2010) è necessario impostare la verbosità di output su Almeno dettagliata per poter individuare il problema.

È possibile che il mio problema fosse un riferimento che in precedenza era un riferimento GAC, ma che non era più il caso dopo la reinstallazione della mia macchina.


1
Vai su Strumenti-> Opzioni-> Progetti e soluzioni-> Crea ed esegui per impostare la verbosità dell'output.
Farshid,

8

Ho avuto lo stesso errore e non sono riuscito a capirlo con le altre risposte. Ho scoperto che possiamo "consolidare" i pacchetti NuGet.

  1. Fare clic con il tasto destro sulla soluzione
  2. Fai clic su Gestisci pacchetti Nuget
  3. Consolida la scheda e aggiorna alla stessa versione.

7

Questo avviso generato per ASP.NET MVC 4 beta predefinito vedi qui

In, qualsiasi cast questo avviso può essere eliminato modificando manualmente il file .csproj per il tuo progetto.

modifica ........: Riferimento Include = "System.Net.Http"

leggere ......: Riferimento Include = "System.Net.Http, Versione = 4.0.0.0"


1
Ho seguito questo e l'errore è scomparso. Ancora non so come o perché, ho avviato un progetto MVC 4 con VS2010 quindi migrato su VS2012. Tuttavia, aggiungendo l'attributo versione, l'errore è scomparso. Grazie
MaiOM

6

Usa un lettore di dipendenze

Utilizzando dep.exe è possibile elencare tutte le dipendenze nidificate di un'intera cartella. Combinato con strumenti unix come grep o awk, può aiutarti a risolvere il tuo problema

Trovare gli assembly a cui si fa riferimento in più di una versione

$ dep | awk '{ print $1 " " $2; print $4 " " $5 }' | awk '{ if (length(versions[$1]) == 0) versions[$1] = $2; if (versions[$1] != $2) errors[$1] = $1; }  END{ for(e in errors) print e } ' 
System.Web.Http            

Questa oscura riga di comando esegue dep.exe quindi reindirizza due volte l'output a Awk

  • mettere genitore e figlio in una singola colonna (per impostazione predefinita ogni riga contiene un genitore e un figlio per esprimere il fatto che questo genitore dipende da quel figlio)
  • quindi esegui una sorta di "raggruppa per" utilizzando una matrice associativa

Comprendere come questo assemblaggio è stato inserito nel cestino

$ dep myproject/bin | grep -i System\.Web\.Http
MyProject-1.0.0.0 >> System.Web.Http.Web-5.2.3.0 2 ( FooLib-1.0.0.0 )
MyProject-1.0.0.0 >> System.Web.Http.Web-4.0.0.0 2 ( BarLib-1.0.0.0 )
FooLib-1.0.0.0 > System.Web.Http.Web-5.2.3.0 1
BarLib-1.0.0.0 > System.Web.Http.Web-4.0.0.0 1 

In questo esempio, lo strumento ti mostrerà che System.Web.Http 5.2.3 proviene dalla tua dipendenza da FooLib mentre la versione 4.0.0 proviene da BarLib.

Quindi puoi scegliere tra

  • convincere i proprietari delle librerie a usare la stessa versione
  • smettere di usarne uno
  • aggiungendo reindirizzamenti vincolanti nel file di configurazione per utilizzare l'ultima versione

Come eseguire queste cose in Windows

Se non si dispone di una shell di tipo unix, è necessario scaricarne una prima di poter eseguire awke grep. Prova una delle seguenti


4

Anch'io ho avuto questo problema e ho usato anche i consigli di AMissico per scoprire il problema (anche se ho dovuto impostare il livello di verbosità su Dettagliato.

Il problema era in realtà abbastanza semplice dopo aver trovato il colpevole.

Background: ho aggiornato il mio progetto da VS2008 a VS2010. In VS2008 il framework di destinazione era 3.5 e quando l'ho portato in VS2010 l'ho passato a 4 (Full). Ho anche aggiornato alcuni componenti di terze parti tra cui i report Crystal.

Si è scoperto che la maggior parte dei riferimenti di sistema puntavano alla versione 4.0.0.0 ma una coppia non era stata cambiata automaticamente (System e System.Web.Services) e stavano ancora guardando 2.0.0.0. Crystal Reports fa riferimento a 4.0.0.0 e quindi è qui che si sono verificati i conflitti. Posizionare semplicemente il cursore sulla prima libreria di sistema in Esplora soluzioni, scorrere l'elenco verso il basso e cercare eventuali riferimenti a 2.0.0.0, rimuovere e aggiungere nuovamente la versione 4.0.0.0 più recente ha funzionato.

Lo strano era che la maggior parte dei riferimenti era stata correttamente aggiornata e se non fosse stato per i report Crystal, probabilmente non l'avrei mai notato ...



2

Come accennato qui , è necessario rimuovere i riferimenti non utilizzati e gli avvisi andranno.


1

ASP.NET build manager sta costruendo il sito Web scorrendo le cartelle in ordine alfabetico e per ogni cartella scopre le dipendenze e crea prima le dipendenze e poi la cartella selezionata.

In questo caso la cartella problematica che è ~ / Controls, è selezionata per essere costruita all'inizio, da un motivo ancora sconosciuto, costruisce alcuni dei controlli lì come un assembly separato anziché all'interno dello stesso assembly di altri controlli (sembra essere collegato al fatto che alcuni controlli dipendono da altri controlli nella stessa cartella).

Quindi la cartella successiva che viene creata (~ / Centro file / Controllo) dipende dalla cartella principale ~ / che dipende da ~ / Controlli, quindi la cartella ~ / Controlli viene ricostruita solo questa volta i controlli che sono stati separati al proprio assemblaggio sono ora uniti allo stesso assemblaggio degli altri controlli a cui viene ancora fatto riferimento l'assemblaggio separato.

Quindi a questo punto 2 assembly (almeno) hanno gli stessi controlli e la build fallisce.

Anche se non sappiamo ancora perché sia ​​successo, siamo stati in grado di aggirare il problema modificando il nome della cartella Controls in ZControls, in questo modo non è stato creato prima ~ / File-Center / Control, solo dopo e in questo modo è costruito come dovrebbe.


1

Soluzione rapida:

Fare clic con il tasto destro del mouse sulla soluzione -> Gestisci pacchetti NuGet per soluzione -> In Consolidate è possibile verificare se sono state installate versioni diverse dello stesso pacchetto. Disinstallare versioni diverse e installare l'ultima.


1

A volte AutoGenerateBindingRedirectsnon è abbastanza (anche con GenerateBindingRedirectsOutputType). Cercare tutte le There was a conflictvoci e correggerle manualmente una per una può essere noioso, quindi ho scritto un piccolo pezzo di codice che analizza l'output del registro e le genera per te (dump a stdout):

// Paste all "there was a conflict" lines from the msbuild diagnostics log to the file below
const string conflictFile = @"C:\AssemblyConflicts.txt";

var sb = new StringBuilder();
var conflictLines = await File.ReadAllLinesAsync(conflictFile);
foreach (var line in conflictLines.Where(l => !String.IsNullOrWhiteSpace(l)))
{
    Console.WriteLine("Processing line: {0}", line);

    var lineComponents = line.Split('"');
    if (lineComponents.Length < 2) 
        throw new FormatException("Unexpected conflict line component count");

    var assemblySegment = lineComponents[1];
    Console.WriteLine("Processing assembly segment: {0}", assemblySegment);
    var assemblyComponents = assemblySegment
                              .Split(",")
                              .Select(kv => kv.Trim())
                              .Select(kv => kv.Split("=")
                              .Last())
                              .ToArray();

    if (assemblyComponents.Length != 4) 
        throw new FormatException("Unexpected conflict segment component count");

    var assembly = assemblyComponents[0];
    var version = assemblyComponents[1];
    var culture = assemblyComponents[2];
    var publicKeyToken = assemblyComponents[3];

    Console.WriteLine("Generating assebmly redirect for Assembly={0}, Version={1}, Culture={2}, PublicKeyToken={3}", assembly, version, culture, publicKeyToken);
    sb.AppendLine($"<dependentAssembly><assemblyIdentity name=\"{assembly}\" publicKeyToken=\"{publicKeyToken}\" culture=\"{culture}\" /><bindingRedirect oldVersion=\"0.0.0.0-{version}\" newVersion=\"{version}\" /></dependentAssembly>");
}

Console.WriteLine("Generated assembly redirects:");
Console.WriteLine(sb);

Suggerimento: utilizzare MSBuild Binary e Structured Log Viewer e generare solo reindirizzamenti vincolanti per i conflitti nel progetto che emette l'avviso (ovvero, solo oltre quelle there was a conflictrighe nel file di testo di input per il codice sopra [ AssemblyConflicts.txt]).


0

Un modo più semplice senza senza tener conto delle dipendenze (interne):

  1. Apri "Esplora soluzioni".
  2. Fai clic su "Mostra tutti i file"
  3. Espandi "Riferimenti"
  4. Vedrai uno (o più) riferimenti con un'icona leggermente diversa rispetto al resto. In genere, è con una scatola gialla che ti suggerisce di prenderne nota. Basta rimuoverlo.
  5. Aggiungi il riferimento indietro e compila il tuo codice.
  6. È tutto.

Nel mio caso, si è verificato un problema con il riferimento MySQL. In qualche modo, potrei elencare tre versioni di esso nell'elenco di tutti i riferimenti disponibili. Ho seguito il processo da 1 a 6 sopra e ha funzionato per me.



0

Se si dispone di un ricaricatore, rimuovere tutti i riferimenti non utilizzati sulla soluzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.