Вирішення MSB3247 - Виявлені конфлікти між різними версіями однієї і тієї ж залежної збірки


427

Рішення .NET 3.5 закінчилося цим попередженням при компіляції з msbuild.

Іноді NDepend може допомогти, але в цьому випадку вона не надає більше деталей. Як і Боб, мені довелося вдатися до відкриття кожної асамблеї в ILDASM, поки я не знайшов той, який посилався на старішу версію залежної збірки.

Я намагався використовувати MSBUILD з VS 2010 Beta 2 (оскільки стаття Connect вказала, що це було зафіксовано у наступній версії CLR), але це не дало більше деталей (можливо, виправлено повідомлення Beta 2)

Чи є кращий (більш автоматизований) підхід?


2
У моєму випадку я просто повинен був переконатися, що всі проекти в рішенні виконують одну і ту ж версію нукетних пакетів (можна просто оновити всі до останнього).
Майкл

Відповіді:


576

Змініть "MSBuild проекту багатозвучності" на "Детально" або вище. Для цього виконайте наступні дії:

  1. Виберіть діалогове вікно Параметри ( Інструменти -> Параметри ... ).
  2. У лівому дереві виберіть вузол Проекти та рішення , а потім виберіть « Створити та виконати» .
    • Примітка. Якщо цей вузол не відображається, переконайтеся, що прапорець у нижній частині діалогового вікна Показати всі налаштування встановлено.
  3. На сторінці інструментів / параметрів, що з’являється, встановіть рівень збірки виводу багатомовності проекту MSBuild у відповідний параметр залежно від вашої версії:

  4. Створіть проект і подивіться у вихідному вікні.

Ознайомтеся з повідомленнями MSBuild. ResolveAssemblyReferencesЗавдання, це завдання , з якою MSB3247 бере своє початок, має допомогти вам налагодити це конкретне питання.

У моєму конкретному випадку було неправильне посилання на SqlServerCe. Дивись нижче. У мене було два проекти, що посилаються на дві різні версії SqlServerCe. Я пішов до проекту зі старшою версією, видалив посилання, потім додав правильну посилання.

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.

Вам не потрібно відкривати кожну збірку для визначення версій посилань на збори.

  • Ви можете перевірити властивості кожної довідки.
  • Відкрийте властивості проекту та перевірте версії розділу Посилання.
  • Відкрийте проекти за допомогою текстового редактора.
  • Використовуйте .Net Reflector.

5
Ваші рішення мені добре виглядають, проте я не думаю, що завжди корисно використовувати розділ "Посилання" для перегляду номерів версій. Я часто бачив, як VS "брешуть" про те, яку версію він використовує, а яку версію насправді згадує у файлі .csproj.
Девід Гардінер

5
@David Gardiner - Я погодився б із вашим "брехливим" твердженням під час використання проектів C #. На мій досвід, проекти C # можуть заплутатися щодо референдуваної версії та фактично складеної / зв'язаної версії. Коли це відбувається, я очищую рішення, видаляю вручну папки bin та obj, а потім видаляю тимчасові збори проекту у% APPDATA%. Рішення відновлення зазвичай вирішує проблему. (VB рідко страждає від цієї конкретної проблеми.)
AMissico

54
win за те, щоб сказати людям реально використовувати вікно Output. Збірка набагато більше, ніж вікно F5 + Список помилок.
JJS

2
Як згадував Ерік Хеемскерк у своїй відповіді, у Visual Studio 2010 вам потрібно буде встановити багатослівний вихід, щоб детально побачити вихід ResolveAssemblyReferences.
Робін Клоуерс

12
Підказка: щоб знайти точне місце у випуску багатослівної збірки, скопіюйте текст у текстовий редактор, знайдіть «Знайдені конфлікти між різними версіями одного залежного складання».
Контанго

133

Майк Хедлоу опублікував невеликий консольний додаток під назвою AsmSpy, який досить добре перераховує посилання кожної збірки:

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

Це набагато швидший спосіб дістатися до основи попереджувального MSB3247, ніж залежати від виходу MSBuild.


1
AsmSpy є приголомшливим, вам просто потрібно пам'ятати, що ви шукаєте посилання на сторонні DLL-файли з невідповідними версіями. Як правило, невідповідні версії посилань на стандартні бібліотеки не спричинять цих попереджень (і їх ви побачите багато).
Тод Томсон

Це чудовий маленький інструмент, який допоміг мені негайно вирішити свою проблему. У моєму випадку, однак, це були не зовсім сторонні DLL, а скоріше посилання на System.Management.Automation.dll, які мали різні посилання на mscorlib.dll.
Кріс Гіллум

Інструмент приємний, однак він не працює за будь-яких обставин. Принаймні для проекту .NET 4.5 він не показав для мене версій, що стикаються. + msbuild output називає питання DLL із шляхами та всіма.
twomm

11
Дякую за добрі слова хлопці :)
Майк Хадлоу

Ви просто врятували мені кілька годин роботи! Це допомогло прочитати детальний вихід, але як тільки я це зробив, було легко знову перевірити за допомогою інструменту.
Норман Н

22

Колись @AMissico відповіді недостатньо. У моєму випадку я не зміг знайти помилку у вікнах Output, тому вирішив створити файл журналу та проаналізувати його, виконавши наступні кроки:

  1. Збереження журналу збірки у файл ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Знайдіть текст: warning MS...або конкретну інформацію попередження: (наприклад, рядок 9293) Found conflicts between different versions...і повна деталізація помилки конфлікту буде вище цього повідомлення (наприклад, рядок 9277)There was a conflicts between... Знайдіть повідомлення про помилку

Visual Studio 2013


Чудовий натяк на пошук 3277 на виході.
sfuqua

21

Я виявив, що (принаймні, у Visual Studio 2010) вам потрібно встановити багатослівний вихід, принаймні докладний, щоб мати можливість виявити проблему.

Можливо, моя проблема була посиланням, яке раніше було посиланням на GAC, але після перевстановлення моєї машини це вже не було.


1
Перейдіть до Інструменти-> Опції-> Проекти та рішення-> Побудуйте та запустіть, щоб встановити багатослівність виводу.
Фаршид

8

У мене була така ж помилка, і я не міг її зрозуміти з іншими відповідями. Я виявив, що ми можемо "консолідувати" пакети NuGet.

  1. Клацніть правою кнопкою миші рішення
  2. Клацніть Управління Nuget пакетами
  3. Об’єднайте вкладку та оновіть до тієї ж версії.

7

Це попередження, створене для бета-версії ASP.NET MVC 4, дивіться тут

У будь-якому ролі цього Попередження можна усунути, вручну редагуючи файл .csproj для вашого проекту.

змінити ........: Довідка включає = "System.Net.Http"

читати ......: Довідка включає = "System.Net.Http, версія = 4.0.0.0"


1
Я стежив за цим, і помилка зникла. Ще не знаю як і чому, я розпочав проект MVC 4 з VS2010, потім мігрував на VS2012. Однак, додавши атрибут версії, помилка зникала. Дякую
MaiOM

6

Використовуйте зчитувач залежності

Використання dep.exe ви можете перерахувати всі вкладені залежності всієї папки. У поєднанні з інструментами unix, такими як grep або awk, вони можуть допомогти вам вирішити вашу проблему

Пошук збірок, на які посилається більш ніж в одній версії

$ 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            

Цей незрозумілий командний рядок запускає dep.exe, а потім передає висновок двічі для пробудження

  • покладіть батьків і дочок в один стовпчик (за замовчуванням кожен рядок містить одного батька та дитину, щоб висловити той факт, що цей батько залежить від цієї дитини)
  • потім зробіть своєрідну 'групу за допомогою' асоціативного масиву

Розуміння того, як ця збірка потрапила у ваш кошик

$ 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 

У цьому прикладі інструмент покаже вам, що System.Web.Http 5.2.3 походить від вашої залежності від FooLib, тоді як версія 4.0.0 походить від BarLib.

Тоді у вас є вибір між

  • переконати власників лібів використовувати одну і ту ж версію
  • припиніть використовувати один з них
  • додавання обов'язкових переадресацій у ваш конфігураційний файл для використання останньої версії

Як запустити цю річ у Windows

Якщо у вас немає оболонки типу unix, вам потрібно буде завантажити її, перш ніж мати змогу запустити awkта grep. Спробуйте одне з наступних


4

У мене теж була ця проблема, і я використовував поради AMissico, щоб виявити проблему (хоча довелося встановити рівень багатослів’я на Детальний.

Проблема була насправді досить прямою, хоча після винуватця.

Передумови: Я модернізував свій проект з VS2008 до VS2010. У VS2008 цільовий фреймворк становив 3,5, і коли я ввів його у VS2010, я перейшов на 4 (повний). Я також оновив деякі сторонні компоненти, включаючи звіти Crystal.

Виявилося, що більшість системних посилань вказують на версію 4.0.0.0, але пара не була змінена автоматично (System and System.Web.Services) і все ще дивилася на 2.0.0.0. Crystal доповіді посилаються на 4.0.0.0, і ось тут виникали конфлікти. Просто поставивши курсор на першу системну бібліотеку в провіднику рішень, курсор внизу списку і шукаючи будь-які посилання на 2.0.0.0, видаливши та повторно додавши новішу версію 4.0.0.0 зробив свою справу.

Дивним було те, що більшість посилань були правильно оновлені, і якби не звіти Crystal, я, мабуть, ніколи б не помітив ...



2

Як згадувалося тут , вам потрібно видалити невикористані посилання, і попередження надійдуть.


1

Менеджер збірки ASP.NET будує веб-сайт, проходячи по папках в алфавітному порядку, і для кожної папки він визначає залежності та спочатку будує залежності, а потім вибрану папку.

У цьому випадку проблематичну папку, яка ~ / Controls, вибирають для створення на початку, з невідомої причини, вона будує деякі елементи управління там як окрему збірку, а не всередині тієї ж збірки, що й інші елементи управління (здається, що бути пов'язаним з тим, що одні елементи управління залежать від інших елементів керування в тій же папці).

Тоді наступна створена папка (~ / Файл-Центр / Керування) залежить від кореневої папки ~ /, яка залежить від ~ / Керування, тому папка ~ / Контролі будується знову лише цього разу розділеними елементами управління. до їх власної збірки тепер приєднуються до тієї ж збірки, що й інші елементи управління, на відокремлену збірку, на яку ще посилаються.

Тож у цьому пункті 2 складання (принаймні) мають однакові елементи керування, і збірка не працює.

Хоча ми досі не знаємо, чому це сталося, нам вдалося обійти це, змінивши ім'я папки Controls на ZControls, таким чином воно не будується до ~ / File-Center / Control, тільки після і таким чином воно будується як слід.


1

Швидке виправлення:

Клацніть правою кнопкою миші рішення -> Керуйте пакетами NuGet для рішення -> У розділі Консолідація можна побачити, чи були встановлені різні версії одного пакету. Видаліть різні версії та встановіть найновішу.


1

Іноді AutoGenerateBindingRedirectsнедостатньо (навіть з GenerateBindingRedirectsOutputType). Пошук усіх There was a conflictзаписів та виправлення їх вручну по черзі може бути стомлюючим, тому я написав невеликий фрагмент коду, який аналізує вихід журналу та генерує їх для вас (скидає 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);

Порада: використовуйте MSBuild Binary and Structured Log Viewer і генеруйте лише переадресації прив’язки для конфліктів у проекті, що надсилає попередження (тобто лише минулі there was a conflictрядки до вхідного текстового файлу для коду вище [ AssemblyConflicts.txt]).


0

Найпростіший спосіб без жодного врахування (внутрішніх) залежностей:

  1. Відкрийте «Провідник рішень».
  2. Натисніть "Показати всі файли"
  3. Розгорнути "Посилання"
  4. Ви побачите одну (або більше) посилань із трохи іншою піктограмою, ніж інші. Зазвичай це жовте поле, що пропонує вам взяти до відома. Просто видаліть його.
  5. Додайте посилання назад і складіть свій код.
  6. Це все.

У моєму випадку виникла проблема з посиланням на MySQL. Якось я міг би перелічити три його версії під списком усіх доступних посилань. Я стежив за процесом від 1 до 6 вище, і він працював на мене.


0

Додаток Visual Studio для Mac Community:

Оскільки відповідь AMissico вимагає зміни рівня журналу, і ні ASMSpy, ні ASMSpyPlus не доступні як кросплатформенне рішення, ось короткий додаток для Visual Studio для Mac:

https://docs.microsoft.com/en-us/visualstudio/mac/compiling-and-building

Це у спільноті Visual Studio → Налаштування ... → Проекти → Журнал складання → багатослівність


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.