Résolution de MSB3247 - Conflits trouvés entre différentes versions du même assembly dépendant

427

Une solution .NET 3.5 s'est retrouvée avec cet avertissement lors de la compilation avec msbuild.

Parfois, NDepend peut aider, mais dans ce cas, il n'a pas donné plus de détails. Comme Bob, j'ai dû recourir à l'ouverture de chaque assembly dans ILDASM jusqu'à ce que je trouve celle qui faisait référence à une ancienne version de l'assembly dépendant.

J'ai essayé d'utiliser MSBUILD à partir de VS 2010 Beta 2 (comme l'article Connect indique que cela a été corrigé dans la prochaine version du CLR) mais cela n'a pas fourni plus de détails non plus (peut-être corrigé après la Bêta 2)

Existe-t-il une meilleure approche (plus automatisée)?

David Gardiner
la source
2
Dans mon cas, je devais juste m'assurer que tous les projets de la solution exécutaient la même version des packages nuget (peuvent simplement tout mettre à jour vers la dernière).
Michael

Réponses:

576

Remplacez la «verbosité de sortie de la construction du projet MSBuild» par «détaillée» ou supérieure. Pour le faire, suivez ces étapes:

  1. Ouvrez la boîte de dialogue Options ( Outils -> Options ... ).
  2. Dans l'arborescence de gauche, sélectionnez nœud Projets et solutions , puis sélectionnez Générer et exécuter .
    • Remarque: si ce nœud n'apparaît pas, assurez-vous que la case en bas de la boîte de dialogue Afficher tous les paramètres est cochée.
  3. Dans la page des outils / options qui apparaît, définissez le niveau de verbosité de la sortie de génération du projet MSBuild sur le paramètre approprié en fonction de votre version:

  4. Générez le projet et regardez dans la fenêtre de sortie.

Consultez les messages MSBuild. leResolveAssemblyReferences tâche, qui est la tâche d'où provient MSB3247, devrait vous aider à déboguer ce problème particulier.

Mon cas spécifique était une référence incorrecte à SqlServerCe. Voir ci-dessous. J'ai eu deux projets référençant deux versions différentes de SqlServerCe. Je suis allé au projet avec l'ancienne version, j'ai supprimé la référence, puis j'ai ajouté la bonne référence.

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.

Vous n'avez pas besoin d'ouvrir chaque assembly pour déterminer les versions des assemblys référencés.

  • Vous pouvez vérifier les propriétés de chaque référence.
  • Ouvrez les propriétés du projet et vérifiez les versions de la section Références.
  • Ouvrez les projets avec un éditeur de texte.
  • Utilisez .Net Reflector.
AMissico
la source
5
Vos solutions me semblent bonnes, mais je ne pense pas qu'il soit toujours utile d'utiliser la section Références pour afficher les numéros de version. J'ai souvent vu VS "mentir" à propos de la version utilisée par rapport à la version réellement mentionnée dans le fichier .csproj.
David Gardiner
5
@David Gardiner - Je serais d'accord avec votre déclaration de "mensonge" lorsque vous utilisez des projets C #. D'après mon expérience, les projets C # peuvent se confondre en ce qui concerne la version référencée et la version réelle compilée / liée. Lorsque cela se produit, je nettoie la solution, supprime manuellement les dossiers bin et obj, puis supprime les assemblys de projet temporaires dans% APPDATA%. Une solution de reconstruction résout généralement le problème. (VB souffre rarement de ce problème spécifique.)
AMissico
54
gagner pour avoir dit aux gens d'utiliser réellement la fenêtre de sortie. La construction est bien plus que la fenêtre F5 + Liste d'erreurs.
JJS
2
Comme ErikHeemskerk l'a mentionné dans sa réponse, dans Visual Studio 2010, vous devrez définir la verbosité de sortie sur détaillée pour voir la sortie de ResolveAssemblyReferences.
Robin Clowers
12
Astuce: pour trouver l'emplacement exact dans la sortie de la construction détaillée, copiez le texte dans un éditeur de texte, recherchez «Conflits trouvés entre différentes versions du même assembly dépendant».
Contango
133

Mike Hadlow a publié une petite application console appelée AsmSpy qui répertorie plutôt bien les références de chaque assemblage:

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

Il s'agit d'un moyen beaucoup plus rapide d'aller au bas de l'avertissement MSB3247 que de dépendre de la sortie MSBuild.

Noel Abrahams
la source
1
AsmSpy est génial, vous devez juste vous rappeler que vous recherchez les références à des DLL tierces avec des versions incompatibles. Généralement, les versions incompatibles dans les références aux bibliothèques standard ne provoqueront pas ces avertissements (et vous les verrez beaucoup).
Tod Thomson
C'est un excellent petit outil qui m'a aidé à résoudre mon problème immédiatement. Dans mon cas, cependant, il ne s'agissait pas exactement de DLL tierces, mais plutôt de références à System.Management.Automation.dll qui avaient des références différentes à mscorlib.dll.
Chris Gillum
L'outil est sympa, cependant, il ne fonctionne pas en toutes circonstances. Au moins pour un projet .NET 4.5, il n'a pas montré les versions des références en collision pour moi. + La sortie msbuild nomme les DLL en question avec des chemins et tout.
twomm
11
Merci pour les gentils mots les gars :)
Mike Hadlow
Tu m'as sauvé quelques heures de travail! Cela a aidé à lire la sortie détaillée, mais une fois que j'ai fait, il a été facile de vérifier à nouveau avec votre outil.
Norman H
22

Parfois, la réponse @AMissico ne suffit pas. Dans mon cas, je n'ai pas trouvé l'erreur dans les fenêtres de sortie, j'ai donc décidé de créer un fichier journal et de l'analyser, en procédant comme suit:

  1. Enregistrement du journal de génération dans un fichier ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Recherchez le texte: warning MS...ou les informations d'avertissement spécifiques: (par exemple, ligne 9293) Found conflicts between different versions...et le détail complet de l'erreur de conflit sera au-dessus de ce message (par exemple, ligne 9277)There was a conflicts between... Trouver le message d'erreur

Visual Studio 2013

Jaider
la source
Excellent indice pour rechercher 3277 dans la sortie.
sfuqua
21

J'ai constaté que (au moins dans Visual Studio 2010), vous devez définir la verbosité de sortie sur au moins détaillée pour pouvoir détecter le problème.

Il se peut que mon problème soit une référence qui était auparavant une référence GAC, mais ce n'était plus le cas après la réinstallation de ma machine.

ErikHeemskerk
la source
1
Allez dans Outils-> Options-> Projets et solutions-> Créer et exécuter pour définir la verbosité de sortie.
Farshid
8

J'ai eu la même erreur et je n'ai pas pu le comprendre avec les autres réponses. J'ai trouvé que nous pouvons «consolider» les packages NuGet.

  1. Clic droit sur la solution
  2. Cliquez sur Gérer les packages Nuget
  3. Consolider l'onglet et mettre à jour vers la même version.
Carol
la source
7

Cet avertissement généré pour la version bêta par défaut d'ASP.NET MVC 4 voir ici

Dans, tout cast de cet avertissement peut être éliminé en modifiant manuellement le fichier .csproj pour votre projet.

modifier ........: Référence Inclure = "System.Net.Http"

à lire ......: Référence Include = "System.Net.Http, Version = 4.0.0.0"

RouR
la source
1
J'ai suivi cela et l'erreur a disparu. Je ne sais toujours pas comment ni pourquoi, j'ai démarré un projet MVC 4 avec VS2010 puis migré sur VS2012. Cependant, l'ajout de l'attribut de version a fait disparaître l'erreur. Merci
MaiOM
6

Utilisez un lecteur de dépendances

À l'aide de dep.exe, vous pouvez répertorier toutes les dépendances imbriquées d'un dossier entier. Combiné avec des outils Unix comme grep ou awk, il peut vous aider à résoudre votre problème

Recherche d'assemblys référencés dans plusieurs versions

$ 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            

Cette ligne de commande obscure exécute dep.exe, puis redirige la sortie deux fois vers awk

  • mettre le parent et l'enfant dans une seule colonne (par défaut, chaque ligne contient un parent et un enfant pour exprimer le fait que ce parent dépend de cet enfant)
  • puis faites une sorte de «groupe» en utilisant un tableau associatif

Comprendre comment cet assemblage a été tiré dans votre bac

$ 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 

Dans cet exemple, l'outil vous montrerait que System.Web.Http 5.2.3 provient de votre dépendance à FooLib tandis que la version 4.0.0 provient de BarLib.

Ensuite, vous avez le choix entre

  • convaincre les propriétaires des bibliothèques d'utiliser la même version
  • arrêtez d'en utiliser un
  • ajouter des redirections de liaison dans votre fichier de configuration pour utiliser la dernière version

Comment exécuter ces choses dans Windows

Si vous n'avez pas de shell de type Unix, vous devrez en télécharger un avant de pouvoir exécuter awket grep. Essayez l'une des solutions suivantes

Manitra Andriamitondra
la source
4

J'ai également eu ce problème et j'ai utilisé les conseils d'AMissico pour découvrir le problème (bien que j'ai dû définir le niveau de verbosité sur Détaillé.

Le problème était en fait assez simple mais après avoir trouvé le coupable.

Contexte: j'ai mis à niveau mon projet de VS2008 à VS2010. Dans VS2008, le cadre cible était de 3,5 et lorsque je l'ai introduit dans VS2010, je l'ai changé en 4 (complet). J'ai également mis à niveau certains composants tiers, y compris les rapports Crystal.

Il s'est avéré que la plupart des références système pointaient vers la version 4.0.0.0 mais qu'un couple n'avait pas été automatiquement modifié (System et System.Web.Services) et regardait toujours 2.0.0.0. Crystal Reports fait référence à 4.0.0.0 et c'est donc là que les conflits se produisaient. Il suffit de placer le curseur sur la première bibliothèque système dans l'explorateur de solutions, de déplacer le curseur vers le bas de la liste et de rechercher des références à 2.0.0.0, de supprimer et de rajouter une version plus récente 4.0.0.0.

Ce qui était étrange, c'est que la plupart des références avaient été correctement mises à jour et si ce n'était pas pour les rapports Crystal, je ne l'aurais probablement jamais remarqué ...

Hamiora
la source
2

Comme mentionné ici , vous devez supprimer les références inutilisées et les avertissements disparaîtront.

lex87
la source
1

Le gestionnaire de génération ASP.NET construit le site Web en parcourant les dossiers par ordre alphabétique, et pour chaque dossier, il comprend ses dépendances et crée d'abord les dépendances, puis le dossier sélectionné.

Dans ce cas, le dossier problématique qui est ~ / Contrôles, est sélectionné pour être construit au début, pour une raison encore inconnue, il y construit certains des contrôles en tant qu'assemblage séparé au lieu de l'intérieur du même assemblage que d'autres contrôles (semble être lié au fait que certains contrôles dépendent d'autres contrôles dans le même dossier).

Ensuite, le dossier suivant qui est construit (~ / Centre de fichiers / Contrôle) dépend du dossier racine ~ / qui dépend de ~ / Contrôles, donc le dossier ~ / Contrôles est reconstruit seulement cette fois les contrôles qui ont été séparés à leur propre assemblage sont désormais joints au même assemblage que les autres contrôles, l'assemblage séparé étant toujours référencé.

Donc, à ce stade, l'assemblage 2 (au moins) a les mêmes contrôles et la génération échoue.

Bien que nous ne sachions toujours pas pourquoi cela s'est produit, nous avons pu contourner ce problème en changeant le nom du dossier Controls en ZControls, de cette façon, il n'est pas construit avant ~ / File-Center / Control, seulement après et de cette façon, il est construit Comme il se doit.

Mike Yinger
la source
1

Solution rapide:

Faites un clic droit sur la solution -> Gérer les packages NuGet pour la solution -> Sous Consolider, vous pouvez voir si différentes versions du même package ont été installées. Désinstallez différentes versions et installez la dernière.

JerryGoyal
la source
1

Parfois, cela AutoGenerateBindingRedirectsne suffit pas (même avec GenerateBindingRedirectsOutputType). La recherche de toutes les There was a conflictentrées et leur correction manuelle une par une peut être fastidieuse, j'ai donc écrit un petit morceau de code qui analyse la sortie du journal et les génère pour vous (dumps to 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);

Astuce: utilisez MSBuild Binary et Structured Log Viewer et générez uniquement des redirections de liaison pour les conflits dans le projet qui émet l'avertissement (c'est-à-dire, uniquement après ces there was a conflictlignes dans le fichier texte d'entrée pour le code ci-dessus [ AssemblyConflicts.txt]).

Ohad Schneider
la source
0

Un moyen le plus simple sans que l'on prenne en compte les dépendances (internes):

  1. Ouvrez "Explorateur de solutions".
  2. Cliquez sur "Afficher tous les fichiers"
  3. Développer "Références"
  4. Vous verrez une (ou plusieurs) référence (s) avec une icône légèrement différente des autres. En règle générale, c'est avec une boîte jaune vous suggérant d'en prendre note. Retirez-le.
  5. Ajoutez la référence et compilez votre code.
  6. C'est tout.

Dans mon cas, il y avait un problème avec la référence MySQL. D'une certaine manière, je pourrais en énumérer trois versions sous la liste de toutes les références disponibles. J'ai suivi les processus 1 à 6 ci-dessus et cela a fonctionné pour moi.

Sukhi
la source
0

Si vous disposez d'un resharper, supprimez toutes les références inutilisées sur votre solution.

Pascal Carmoni
la source