การแก้ไข MSB3247 - พบข้อขัดแย้งระหว่างแอสเซมบลีเวอร์ชันเดียวกันที่ต่างกัน


427

โซลูชัน. NET 3.5 สิ้นสุดลงด้วยคำเตือนนี้เมื่อคอมไพล์ด้วย msbuild

บางครั้ง NDepend อาจช่วยเหลือ แต่ในกรณีนี้มันไม่ได้ให้รายละเอียดเพิ่มเติมใด ๆ เช่นเดียวกับบ๊อบฉันต้องหันไปเปิดการชุมนุมแต่ละครั้งใน ILDASM จนกว่าฉันจะพบที่อ้างอิงถึงเวอร์ชั่นเก่าของแอสเซมบลีที่ขึ้นต่อกัน

ฉันลองใช้ MSBUILD จาก VS 2010 Beta 2 (เนื่องจากบทความ Connect ระบุว่าได้รับการแก้ไขใน CLR รุ่นถัดไป) แต่ไม่ได้ให้รายละเอียดเพิ่มเติมอีก (อาจจะโพสต์ที่มีการแก้ไขเบต้า 2)

มีวิธีที่ดีกว่า (อัตโนมัติมากขึ้น)?


2
ในกรณีของฉันฉันต้องตรวจสอบให้แน่ใจว่าโครงการทั้งหมดที่อยู่ในโซลูชันนั้นใช้แพ็คเกจ nuget รุ่นเดียวกัน (สามารถอัปเดตเป็นเวอร์ชั่นล่าสุดทั้งหมดได้)
Michael

คำตอบ:


576

เปลี่ยน "รายละเอียดการสร้างผลลัพธ์โครงการสร้าง MSBuild" เป็น "ละเอียด" ขึ้นไป โดยทำตามขั้นตอนต่อไปนี้:

  1. เปิดกล่องโต้ตอบตัวเลือก ( เครื่องมือ -> ตัวเลือก ... )
  2. ในต้นไม้ซ้ายมือเลือกโครงการและโซลูชั่นโหนดและจากนั้นเลือกสร้างและเรียกใช้
    • หมายเหตุ: หากโหนดนี้ไม่ปรากฏขึ้นให้แน่ใจว่าช่องทำเครื่องหมายที่ด้านล่างของกล่องโต้ตอบที่แสดงการตั้งค่าทั้งหมดจะถูกตรวจสอบ
  3. ในหน้าเครื่องมือ / ตัวเลือกที่ปรากฏขึ้นให้ตั้งค่าระดับการสร้างรายละเอียด verbosity ของโครงการสร้าง 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.

คุณไม่จำเป็นต้องเปิดแต่ละชุดประกอบเพื่อตรวจสอบรุ่นของชุดประกอบที่อ้างอิง

  • คุณสามารถตรวจสอบคุณสมบัติของข้อมูลอ้างอิงแต่ละรายการ
  • เปิดคุณสมบัติโครงการและตรวจสอบรุ่นของส่วนอ้างอิง
  • เปิดโครงการด้วย Text Editor
  • ใช้. Net Reflector

5
วิธีแก้ปัญหาของคุณดูดีสำหรับฉัน แต่ฉันไม่คิดว่ามันจะมีประโยชน์เสมอที่จะใช้ส่วนการอ้างอิงเพื่อดูหมายเลขรุ่น ฉันมักจะเห็น VS "โกหก" กับฉันเกี่ยวกับเวอร์ชันที่ใช้กับเวอร์ชันที่กล่าวถึงจริงในไฟล์. csproj
David Gardiner

5
@David Gardiner - ฉันจะเห็นด้วยกับคำสั่ง "โกหก" ของคุณเมื่อใช้โครงการ C # จากประสบการณ์ของฉันโครงการ C # อาจสับสนเกี่ยวกับเวอร์ชันที่อ้างอิงและเวอร์ชันจริงที่คอมไพล์ / เชื่อมโยง เมื่อสิ่งนี้เกิดขึ้นฉันทำความสะอาดโซลูชันลบโฟลเดอร์ bin และ obj ด้วยตนเองจากนั้นลบแอสเซมบลีโครงการชั่วคราวใน% APPDATA% โซลูชันการสร้างใหม่มักแก้ไขปัญหาได้ (VB ไม่ค่อยได้รับความทุกข์จากปัญหาเฉพาะนี้)
AMissico

54
ชนะเพื่อบอกให้ผู้คนใช้หน้าต่างผลลัพธ์จริง ๆ Build เป็นมากกว่าหน้าต่างรายการข้อผิดพลาด F5 +
JJS

2
ดังที่ ErikHeemskerk พูดถึงในคำตอบของเขาใน Visual Studio 2010 คุณจะต้องตั้งค่า verbosity ให้เป็นรายละเอียดเพื่อดูผลลัพธ์ของ ResolveAssemblyReferences
Robin Clowers

12
คำแนะนำ: เพื่อค้นหาจุดที่แน่นอนในผลลัพธ์การสร้าง verbose ให้คัดลอกข้อความไปยังโปรแกรมแก้ไขข้อความค้นหา "ข้อขัดแย้งที่พบระหว่างเวอร์ชันต่าง ๆ ของแอสเซมบลีที่ขึ้นต่อกันรุ่นเดียวกัน"
Contango

133

Mike Hadlow ได้โพสต์แอปคอนโซลเล็ก ๆ ชื่อว่า 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 นั้นยอดเยี่ยมคุณต้องจำไว้ว่าคุณกำลังมองหาการอ้างอิงถึง DLLs ของบุคคลที่สามที่มีรุ่นที่ไม่ตรงกัน โดยทั่วไปแล้วเวอร์ชันที่ไม่ตรงกันในการอ้างอิงกับไลบรารีมาตรฐานจะไม่ทำให้เกิดคำเตือนเหล่านี้ (และคุณจะเห็นพวกเขามาก)
ท็อดทอมสัน

นี่เป็นเครื่องมือเล็ก ๆ ที่ยอดเยี่ยมซึ่งช่วยให้ฉันแก้ปัญหาของฉันได้ทันที ในกรณีของฉัน แต่มันก็ไม่ได้เป็น DLLs ของบุคคลที่สามอย่างแน่นอน แต่ค่อนข้างอ้างอิงถึง System.Management.Automation.dll ซึ่งมีการอ้างอิงที่แตกต่างกันเพื่อ mscorlib.dll
Chris Gillum

เครื่องมือนี้ใช้งานได้ดี แต่ไม่สามารถใช้งานได้ในทุกสถานการณ์ อย่างน้อยสำหรับโปรเจ็กต์. NET 4.5 มันไม่ได้แสดงการอ้างอิงที่ขัดแย้งกันสำหรับฉัน + msbuild เอาต์พุตตั้งชื่อ DLLs ที่เป็นปัญหาด้วยพา ธ และทั้งหมด
twomm

11
ขอบคุณสำหรับคำที่ใจดี :)
Mike Hadlow

คุณช่วยฉันทำงานหลายชั่วโมง! มันช่วยในการอ่านผลลัพธ์ที่มีรายละเอียด แต่เมื่อฉันทำมันเป็นเรื่องง่ายที่จะตรวจสอบอีกครั้งด้วยเครื่องมือของคุณ
นอร์แมน H

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) คุณต้องตั้งค่า verbosity ให้เป็นรายละเอียดอย่างน้อยเพื่อให้สามารถมองเห็นปัญหาได้

อาจเป็นได้ว่าปัญหาของฉันคือการอ้างอิงที่ก่อนหน้านี้เป็นการอ้างอิง GAC แต่นั่นไม่ใช่กรณีหลังจากติดตั้งเครื่องของฉันอีกต่อไป


1
ไปที่ Tools-> Options-> Projects and Solutions-> Build and Run เพื่อตั้ง verbosity เอาท์พุท
Farshid

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 จากนั้นไปป์ที่เอาต์พุตสองครั้งเพื่อ awk

  • ย้ายพาเรนต์และชายด์ในคอลัมน์เดียว (โดยค่าเริ่มต้นแต่ละบรรทัดมีหนึ่งพาเรนต์และชายด์เพื่อแสดงความจริงที่พาเรนต์นี้ขึ้นอยู่กับชายด์นั้น)
  • จากนั้นทำ 'group by' โดยใช้อาร์เรย์ที่เชื่อมโยงกัน

ทำความเข้าใจเกี่ยวกับวิธีดึงชุดประกอบนี้ในถังขยะของคุณ

$ 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

จากนั้นคุณมีทางเลือกระหว่าง

  • โน้มน้าวใจเจ้าของ libs ให้ใช้เวอร์ชั่นเดียวกัน
  • หยุดใช้หนึ่งพวกเขา
  • การเพิ่มการเปลี่ยนเส้นทางการผูกในไฟล์ปรับแต่งของคุณเพื่อใช้เวอร์ชั่นล่าสุด

วิธีเรียกใช้สิ่งเหล่านี้ใน Windows

หากคุณไม่ได้มีประเภทเปลือกยูนิกซ์คุณจะต้องดาวน์โหลดหนึ่งก่อนที่ความสามารถในการทำงานและawk grepลองทำอย่างใดอย่างหนึ่งต่อไปนี้


4

ฉันมีปัญหานี้เช่นกันและใช้คำแนะนำของ AMissico เช่นกันในการค้นพบปัญหา

ปัญหานี้ค่อนข้างตรงไปตรงมาแม้ว่าหลังจากพบผู้กระทำผิด

ความเป็นมา: ฉันอัพเกรดโครงการจาก VS2008 เป็น VS2010 ใน VS2008 กรอบงานเป้าหมายคือ 3.5 และเมื่อฉันนำเข้าสู่ VS2010 ฉันเปลี่ยนเป็น 4 (เต็ม) ฉันยังอัปเกรดส่วนประกอบของบุคคลที่สามรวมถึงรายงาน Crystal

มันเปิดการอ้างอิงระบบส่วนใหญ่ที่ชี้ไปที่รุ่น 4.0.0.0 แต่คู่ไม่ได้ถูกเปลี่ยนแปลงโดยอัตโนมัติ (ระบบและ System.Web.Services) และยังคงดูที่ 2.0.0.0 รายงาน Crystal อ้างอิง 4.0.0.0 และนี่คือสิ่งที่เกิดความขัดแย้ง เพียงวางเคอร์เซอร์ไว้ที่ไลบรารีระบบแรกในตัวสำรวจโซลูชันเลื่อนเคอร์เซอร์ลงในรายการแล้วมองหาการอ้างอิงใด ๆ ถึง 2.0.0.0 การลบและการเพิ่มเวอร์ชัน 4.0.0.0 ที่ใหม่กว่านั้นทำขึ้นมาใหม่

แปลกนี่คือที่อ้างอิงส่วนใหญ่ได้รับการปรับปรุงอย่างถูกต้องและหากไม่ได้สำหรับรายงาน Crystal ฉันอาจจะไม่เคยสังเกตเห็น ...




1

ASP.NET build manager กำลังสร้างเว็บไซต์โดยดำเนินการตามลำดับตัวอักษรและสำหรับแต่ละโฟลเดอร์จะมีการอ้างอิงและสร้างการขึ้นต่อกันก่อนจากนั้นเลือกโฟลเดอร์

ในกรณีนี้โฟลเดอร์ที่มีปัญหาซึ่งเป็น ~ / การควบคุมถูกเลือกให้สร้างขึ้นที่จุดเริ่มต้นจากยังไม่ทราบสาเหตุมันสร้างตัวควบคุมบางส่วนที่นั่นเป็นแอสเซมบลีที่แยกต่างหากแทนภายในแอสเซมบลีเดียวกันกับตัวควบคุมอื่น ๆ เชื่อมต่อกับความจริงที่ว่าการควบคุมบางอย่างขึ้นอยู่กับการควบคุมอื่น ๆ ในโฟลเดอร์เดียวกัน)

จากนั้นโฟลเดอร์ถัดไปที่สร้างขึ้น (~ / File-Center / Control) จะขึ้นอยู่กับโฟลเดอร์ราก ~ / ซึ่งขึ้นอยู่กับ ~ / การควบคุมดังนั้นโฟลเดอร์ ~ / การควบคุมจะถูกสร้างขึ้นอีกครั้งในเวลานี้การควบคุมที่ถูกแยกออก ในแอสเซมบลีของตนเองตอนนี้เข้าร่วมกับแอสเซมบลีเดียวกันเป็นตัวควบคุมอื่น ๆ ด้วยแอสเซมบลีที่แยกต่างหากยังคงถูกอ้างอิง

ดังนั้น ณ จุดนี้การชุมนุม 2 (อย่างน้อย) มีการควบคุมเดียวกันและการสร้างล้มเหลว

แม้ว่าเราจะยังไม่ทราบสาเหตุที่เกิดขึ้น แต่เราสามารถแก้ไขได้โดยเปลี่ยนชื่อโฟลเดอร์การควบคุมเป็น 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 และ Structured Log Viewerและสร้างการเปลี่ยนเส้นทางการเชื่อมโยงสำหรับความขัดแย้งในโครงการที่ส่งคำเตือนเท่านั้น (นั่นคือผ่านthere was a conflictบรรทัดเหล่านั้นไปยังไฟล์ข้อความอินพุตสำหรับรหัสด้านบน [ AssemblyConflicts.txt])


0

วิธีที่ง่ายที่สุดโดยไม่มีใครคำนึงถึงการพึ่งพา (ภายใน):

  1. เปิด "โซลูชัน Explorer"
  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 →การกำหนดค่า ... →โครงการ→สร้างบันทึก→การใช้คำฟุ่มเฟือย


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.