Rozwiązanie MSB3247 - Znaleziono konflikty między różnymi wersjami tego samego zestawu zależnego

427

Rozwiązanie .NET 3.5 zakończyło się tym ostrzeżeniem podczas kompilacji z msbuild.

Czasami NDepend może pomóc, ale w tym przypadku nie podał żadnych dalszych szczegółów. Podobnie jak Bob, musiałem uciekać się do otwierania każdego zestawu w ILDASM, dopóki nie znalazłem tego, który odwoływał się do starszej wersji zestawu zależnego.

Próbowałem użyć MSBUILD z VS 2010 Beta 2 (jak wskazał artykuł Connect w następnej wersji CLR), ale nie dostarczyło to również żadnych szczegółów (być może naprawiono po Beta 2)

Czy istnieje lepsze (bardziej zautomatyzowane) podejście?

David Gardiner
źródło
2
W moim przypadku musiałem tylko upewnić się, że wszystkie projekty w rozwiązaniu miały uruchomioną tę samą wersję pakietów nuget (można po prostu zaktualizować wszystkie do najnowszej wersji).
Michael,

Odpowiedzi:

576

Zmień „Szczegółowość danych wyjściowych kompilacji projektu MSBuild” na „Szczegółowe” lub wyżej. Aby to zrobić, wykonaj następujące kroki:

  1. Wyświetl okno dialogowe Opcje ( Narzędzia -> Opcje ... ).
  2. W drzewie po lewej stronie wybierz węzeł Projekty i rozwiązania , a następnie wybierz Kompiluj i uruchom .
    • Uwaga: jeśli ten węzeł się nie pojawi, upewnij się, że pole wyboru u dołu okna dialogowego Pokaż wszystkie ustawienia jest zaznaczone.
  3. Na wyświetlonej stronie narzędzi / opcji ustaw poziom szczegółowości wyjściowej kompilacji projektu MSBuild na odpowiednie ustawienie w zależności od wersji:

  4. Zbuduj projekt i spójrz w okno wyjściowe.

Sprawdź wiadomości MSBuild. ResolveAssemblyReferencesZadanie, które jest zadaniem, z którego pochodzi MSB3247 powinno pomóc debugowania tego konkretnego problemu.

Mój konkretny przypadek był niepoprawnym odniesieniem do SqlServerCe. Patrz poniżej. Miałem dwa projekty odwołujące się do dwóch różnych wersji SqlServerCe. Poszedłem do projektu ze starszą wersją, usunąłem referencję, a następnie dodałem poprawną referencję.

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.

Nie trzeba otwierać każdego zestawu, aby określić wersje zespołów, do których istnieją odniesienia.

  • Możesz sprawdzić właściwości każdego odwołania.
  • Otwórz właściwości projektu i sprawdź wersje sekcji Odwołania.
  • Otwórz projekty za pomocą edytora tekstu.
  • Użyj .Net Reflector.
AMissico
źródło
5
Twoje rozwiązania wyglądają dla mnie dobrze, jednak nie sądzę, że zawsze przydatne jest używanie sekcji Referencje do przeglądania numerów wersji. Często widziałem, że VS „okłamuje mnie” na temat używanej wersji w porównaniu z wersją wymienioną w pliku .csproj.
David Gardiner
5
@David Gardiner - Zgadzam się z twoim „kłamliwym” stwierdzeniem podczas korzystania z projektów C #. Z mojego doświadczenia wynika, że ​​projekty w języku C # mogą się mylić, jeśli chodzi o wersję, do której istnieje odniesienie, i faktyczną wersję skompilowaną / połączoną. Kiedy tak się dzieje, czyszczę rozwiązanie, ręcznie usuwam foldery bin i obj, a następnie usuwam tymczasowe zespoły projektu w% APPDATA%. Rozwiązanie przebudowy zwykle rozwiązuje problem. (VB rzadko cierpi z powodu tego konkretnego problemu.)
AMissico,
54
wygrana za mówienie ludziom, aby faktycznie korzystali z okna Wyjście. Kompilacja to znacznie więcej niż okno F5 + Lista błędów.
JJS
2
Jak wspomniał ErikHeemskerk w swojej odpowiedzi, w programie Visual Studio 2010 trzeba ustawić szczegółowość danych wyjściowych na szczegółowe, aby zobaczyć dane wyjściowe ResolveAssemblyReferences.
Robin Clowers
12
Wskazówka: aby znaleźć dokładne miejsce w pełnych wynikach kompilacji, skopiuj tekst do edytora tekstów, wyszukaj „Znaleziono konflikty między różnymi wersjami tego samego zależnego zestawu”.
Contango,
133

Mike Hadlow opublikował małą aplikację konsolową o nazwie AsmSpy, która dość ładnie wymienia odniesienia do każdego zestawu:

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

Jest to znacznie szybszy sposób dotarcia do dolnej części ostrzeżenia MSB3247, niż poleganie na danych wyjściowych MSBuild.

Noel Abrahams
źródło
1
AsmSpy jest niesamowity, musisz tylko pamiętać, że szukasz odwołań do bibliotek DLL stron trzecich w niedopasowanych wersjach. Zasadniczo niedopasowane wersje w odniesieniach do bibliotek standardowych nie powodują tych ostrzeżeń (i zobaczysz je dużo).
Tod Thomson,
To wspaniałe małe narzędzie, które pomogło mi natychmiast rozwiązać problem. W moim przypadku jednak nie były to biblioteki DLL stron trzecich, ale odniesienia do System.Management.Automation.dll, które miały różne odniesienia do mscorlib.dll.
Chris Gillum,
Narzędzie jest fajne, jednak nie działa we wszystkich okolicznościach. Przynajmniej dla projektu .NET 4.5 nie pokazał mi kolidujących wersji referencji. Dane wyjściowe + msbuild nazwują te biblioteki DLL ścieżkami i wszystkimi innymi.
twomm
11
Dzięki za miłe słowa chłopaki :)
Mike Hadlow
Właśnie zaoszczędziłeś mi kilka godzin pracy! Pomogło mi to przeczytać szczegółowe dane wyjściowe, ale kiedy to zrobiłem, łatwo było ponownie zweryfikować za pomocą narzędzia.
Norman H
22

Kiedyś odpowiedź @AMissico nie wystarczy. W moim przypadku nie mogłem znaleźć błędu w oknach danych wyjściowych, dlatego postanowiłem utworzyć plik dziennika i przeanalizować go, wykonując następujące czynności:

  1. Zapisywanie dziennika kompilacji w pliku ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Znajdź tekst: warning MS...lub szczegółowe informacje ostrzegawcze: (np. Wiersz 9293), Found conflicts between different versions...a pełne szczegóły błędu konfliktu znajdą się nad tym komunikatem (np. Wiersz 9277)There was a conflicts between... Znajdź komunikat o błędzie

Visual Studio 2013

Jaider
źródło
Świetna wskazówka do wyszukiwania 3277 w danych wyjściowych.
sfuqua
21

Odkryłem, że (przynajmniej w Visual Studio 2010) musisz ustawić szczegółowość wyjściową na co najmniej Szczegółową, aby móc wykryć problem.

Być może moim problemem było odwołanie, które wcześniej było odniesieniem GAC, ale nie było już tak po ponownej instalacji mojego komputera.

ErikHeemskerk
źródło
1
Przejdź do Narzędzia-> Opcje-> Projekty i rozwiązania-> Kompiluj i uruchamiaj, aby ustawić szczegółowość danych wyjściowych.
Farshid
8

Miałem ten sam błąd i nie mogłem go zrozumieć z innymi odpowiedziami. Odkryłem, że możemy „konsolidować” pakiety NuGet.

  1. Kliknij rozwiązanie prawym przyciskiem myszy
  2. Kliknij Zarządzaj pakietami Nuget
  3. Konsoliduj kartę i aktualizuj do tej samej wersji.
kolęda
źródło
7

To ostrzeżenie wygenerowane dla domyślnej wersji ASP.NET MVC 4 beta, patrz tutaj

W każdej obsadzie to ostrzeżenie można wyeliminować, ręcznie edytując plik .csproj dla swojego projektu.

modyfikuj ........: Reference Include = "System.Net.Http"

do odczytu ......: Reference Include = "System.Net.Http, Version = 4.0.0.0"

RouR
źródło
1
Postępowałem zgodnie z tym, a błąd zniknął. Nadal nie wiem jak i dlaczego, rozpocząłem projekt MVC 4 z VS2010, a następnie przeprowadziłem migrację na VS2012. Jednak dodanie atrybutu wersji sprawiło, że błąd zniknął. Dzięki
MaiOM
6

Użyj czytnika zależności

Korzystanie z dep.exe można wyświetlić listę wszystkich zagnieżdżonych zależności całego folderu. W połączeniu z narzędziami uniksowymi, takimi jak grep lub awk, może pomóc rozwiązać problem

Znajdowanie zestawów, do których istnieją odniesienia w więcej niż jednej wersji

$ 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            

Ten niejasny wiersz poleceń uruchamia dep.exe, a następnie przesyła dane wyjściowe dwukrotnie, aby uzyskać awk

  • umieść element nadrzędny i element podrzędny w jednej kolumnie (domyślnie każdy wiersz zawiera jednego element nadrzędny i element podrzędny, aby wyrazić fakt, że ten element nadrzędny zależy od tego elementu podrzędnego)
  • następnie zrób coś w rodzaju „grupuj według”, używając tablicy asocjacyjnej

Zrozumienie, w jaki sposób ten zestaw został wciągnięty do kosza

$ 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 

W tym przykładzie narzędzie pokazuje, że System.Web.Http 5.2.3 pochodzi z zależności od FooLib, podczas gdy wersja 4.0.0 pochodzi z BarLib.

Następnie masz wybór między

  • przekonanie właścicieli bibliotek do korzystania z tej samej wersji
  • przestań ich używać
  • dodanie przekierowań powiązań w pliku konfiguracyjnym, aby użyć najnowszej wersji

Jak uruchomić te rzeczy w systemie Windows

Jeśli nie masz powłoki typu unix, musisz ją pobrać przed uruchomieniem awki uruchomieniem grep. Wypróbuj jedną z poniższych opcji

Manitra Andriamitondra
źródło
4

Miałem też ten problem i skorzystałem z porad AMissico, aby odkryć problem (chociaż musiałem ustawić poziom szczegółowości na Szczegółowy.

Problem był jednak całkiem prosty po znalezieniu winowajcy.

Tło: Zaktualizowałem swój projekt z VS2008 do VS2010. W VS2008 docelowy framework był 3.5, a kiedy wprowadziłem go do VS2010, zmieniłem go na 4 (pełny). Uaktualniłem także niektóre komponenty stron trzecich, w tym raporty Crystal.

Okazało się, że większość odniesień do systemu wskazywała na wersję 4.0.0.0, ale kilka nie zostało automatycznie zmienionych (System i System.Web.Services) i nadal patrzyło na 2.0.0.0. Raporty Crystal odnoszą się do 4.0.0.0, a więc w tym miejscu występowały konflikty. Wystarczy umieścić kursor na pierwszej bibliotece Systemu w eksploratorze rozwiązań, przesunąć kursor w dół listy i poszukać odniesień do 2.0.0.0, usunąć i ponownie dodać nowszą wersję 4.0.0.0.

Dziwne, że większość referencji została poprawnie zaktualizowana i gdyby nie raporty Crystal, prawdopodobnie nigdy bym nie zauważył ...

Hamiora
źródło
2

Zrobiłem aplikację na podstawie aplikacji Mike'a Hadlowa: AsmSpy .

Moja aplikacja jest aplikacją WPF z graficznym interfejsem użytkownika i można ją pobrać z mojego domowego serwera internetowego: AsmSpyPlus.exe .

Kod jest dostępny na: GitHub

Próbka Gui

Eric Ouellet
źródło
2

Jak wspomniano tutaj , musisz usunąć nieużywane odniesienia, a ostrzeżenia znikną.

lex87
źródło
1

Menedżer kompilacji ASP.NET buduje stronę internetową, przeglądając foldery alfabetycznie, i dla każdego folderu odkrywa zależności i najpierw buduje zależności, a następnie wybrany folder.

W tym przypadku problematyczny folder, który jest ~ / Controls, został wybrany do zbudowania na początku, z jeszcze nieznanego powodu, buduje tam niektóre formanty jako oddzielny zestaw zamiast w tym samym zestawie, co inne formanty (wydaje się, że być powiązanym z faktem, że niektóre kontrolki zależą od innych kontrolek w tym samym folderze).

Następnie następny budowany folder (~ / File-Center / Control) jest zależny od folderu głównego ~ /, który jest zależny od ~ / Controls, więc folder ~ / Controls jest budowany ponownie tylko tym razem, które zostały rozdzielone do własnego zestawu są teraz połączone z tym samym zestawem, co inne elementy sterujące, a do oddzielnego zestawu wciąż się odwołuje.

Więc w tym momencie zestaw 2 (przynajmniej) ma te same elementy sterujące i kompilacja kończy się niepowodzeniem.

Chociaż nadal nie wiemy, dlaczego tak się stało, byliśmy w stanie obejść ten problem, zmieniając nazwę folderu Controls na ZControls, w ten sposób nie jest on budowany przed ~ / File-Center / Control, tylko później i w ten sposób jest budowany jak powinno.

Mike Yinger
źródło
1

Szybka naprawa:

Kliknij prawym przyciskiem myszy rozwiązanie -> Zarządzaj pakietami NuGet dla rozwiązania -> W obszarze Konsoliduj możesz sprawdzić, czy zostały zainstalowane różne wersje tego samego pakietu. Odinstaluj różne wersje i zainstaluj najnowszą.

JerryGoyal
źródło
1

Czasami AutoGenerateBindingRedirectsto nie wystarcza (nawet przy GenerateBindingRedirectsOutputType). Wyszukiwanie wszystkich There was a conflictwpisów i ręczne ich poprawianie jeden po drugim może być żmudne, dlatego napisałem mały fragment kodu, który analizuje dane wyjściowe dziennika i generuje je dla ciebie (zrzuty do 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);

Wskazówka: używaj MSBuild Binary and Structured Log Viewer i generuj tylko przekierowania wiązania dla konfliktów w projekcie, który emituje ostrzeżenie (to znaczy, tylko za tymi there was a conflictliniami do wejściowego pliku tekstowego dla kodu powyżej [ AssemblyConflicts.txt]).

Ohad Schneider
źródło
0

Najprostszy sposób bez uwzględnienia (wewnętrznych) zależności:

  1. Otwórz „Solution Explorer”.
  2. Kliknij „Pokaż wszystkie pliki”
  3. Rozwiń „Referencje”
  4. Zobaczysz jeden (lub więcej) odnośników z nieco inną ikoną niż reszta. Zazwyczaj jest to żółte pole sugerujące zanotowanie go. Po prostu to usuń.
  5. Dodaj referencję i skompiluj kod.
  6. To wszystko.

W moim przypadku wystąpił problem z referencją MySQL. Jakoś mógłbym wymienić trzy jego wersje pod listą wszystkich dostępnych referencji. Postępowałem zgodnie z powyższą procedurą od 1 do 6 i zadziałało to dla mnie.

Sukhi
źródło
0

Jeśli masz resharper, usuń wszystkie nieużywane odniesienia w swoim rozwiązaniu.

Pascal Carmoni
źródło