Resolución de MSB3247: conflictos encontrados entre diferentes versiones del mismo ensamblado dependiente

427

Una solución .NET 3.5 terminó con esta advertencia al compilar con msbuild.

A veces, NDepend puede ayudar, pero en este caso no dio más detalles. Al igual que Bob , terminé teniendo que recurrir a la apertura de cada ensamblaje en ILDASM hasta que encontré el que hacía referencia a una versión anterior del ensamblaje dependiente.

Intenté usar MSBUILD de VS 2010 Beta 2 (como el artículo de Connect indicaba que esto se solucionó en la próxima versión del CLR) pero eso tampoco proporcionó más detalles (tal vez solucionado después de Beta 2)

¿Existe un enfoque mejor (más automatizado)?

David Gardiner
fuente
2
En mi caso, solo tenía que asegurarme de que todos los proyectos de la solución ejecutaran la misma versión de paquetes nuget (simplemente puede actualizar todos a la última versión).
Michael

Respuestas:

576

Cambie el "nivel de detalle de salida de compilación del proyecto MSBuild" a "Detallado" o superior. Para hacer esto, siga estos pasos:

  1. Abra el cuadro de diálogo Opciones ( Herramientas -> Opciones ... ).
  2. En el árbol de la izquierda, seleccione el nodo Proyectos y soluciones , y luego seleccione Compilar y ejecutar .
    • Nota: si este nodo no aparece, asegúrese de que la casilla de verificación en la parte inferior del cuadro de diálogo muestre todas las configuraciones esté marcada.
  3. En la página de herramientas / opciones que aparece, configure el detalle de salida de compilación del proyecto MSBuild en la configuración adecuada según su versión:

  4. Construye el proyecto y mira en la ventana de salida.

Echa un vistazo a los mensajes de MSBuild. losResolveAssemblyReferences tarea, que es la tarea de la que se origina MSB3247, debería ayudarlo a depurar este problema en particular.

Mi caso específico fue una referencia incorrecta a SqlServerCe. Vea abajo. Tuve dos proyectos que hacen referencia a dos versiones diferentes de SqlServerCe. Fui al proyecto con la versión anterior, eliminé la referencia y luego agregué la referencia correcta.

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.

No tiene que abrir cada conjunto para determinar las versiones de los conjuntos referenciados.

  • Puede verificar las Propiedades de cada Referencia.
  • Abra las propiedades del proyecto y verifique las versiones de la sección Referencias.
  • Abra los proyectos con un editor de texto.
  • Utilice .Net Reflector.
Amissico
fuente
55
Sus soluciones me parecen buenas, sin embargo, no creo que siempre sea útil usar la sección Referencias para ver los números de versión. A menudo he visto a VS "mentirme" acerca de qué versión está usando frente a qué versión se menciona realmente en el archivo .csproj.
David Gardiner
55
@David Gardiner: estaría de acuerdo con su declaración de "mentira" al usar proyectos de C #. En mi experiencia, los proyectos de C # pueden confundirse con respecto a la versión referenciada y la versión real compilada / vinculada. Cuando esto sucede, limpio la solución, elimino manualmente las carpetas bin y obj, luego elimino los ensamblados temporales del proyecto en% APPDATA%. Una solución de reconstrucción generalmente resuelve el problema. (VB rara vez sufre de este problema específico.)
AMissico
54
ganar por decirle a la gente que realmente use la ventana Salida. Build es mucho más que la ventana F5 + Lista de errores.
JJS
2
Como ErikHeemskerk mencionó en su respuesta, en Visual Studio 2010 deberá establecer la verbosidad de salida en detallada para ver la salida de ResolveAssemblyReferences.
Robin Clowers
12
Sugerencia: para encontrar el lugar exacto en la salida de compilación detallada, copie el texto en un editor de texto, busque "Conflictos encontrados entre diferentes versiones del mismo ensamblado dependiente".
Contango
133

Mike Hadlow ha publicado una pequeña aplicación de consola llamada AsmSpy que enumera bastante bien las referencias de cada ensamblaje:

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

Esta es una forma mucho más rápida de llegar al final de la advertencia MSB3247, que depender de la salida de MSBuild.

Noel Abrahams
fuente
1
AsmSpy es increíble, solo necesita recordar que está buscando referencias a archivos DLL de terceros con versiones que no coinciden. En general, las versiones que no coinciden en las referencias a las bibliotecas estándar no causarán estas advertencias (y las verá mucho).
Tod Thomson
Esta es una gran herramienta que me ayudó a resolver mi problema de inmediato. En mi caso, sin embargo, no se trataba exactamente de archivos DLL de terceros, sino más bien referencias a System.Management.Automation.dll que tenían diferentes referencias a mscorlib.dll.
Chris Gillum
La herramienta es buena, sin embargo, no funciona en todas las circunstancias. Al menos para un proyecto .NET 4.5 no mostró las versiones de referencias colisionantes para mí. + msbuild output nombra las DLL en cuestión con rutas y todo.
twomm
11
Gracias por las amables palabras chicos :)
Mike Hadlow
¡Me acabas de salvar algunas horas de trabajo! Ayudó a leer la salida detallada, pero una vez que lo hice, fue fácil volver a verificar con su herramienta.
Norman H
22

En algún momento la respuesta de @AMissico no es suficiente. En mi caso, no pude encontrar el error en las ventanas de Salida, así que decidí crear un archivo de registro y analizarlo, siguiendo los siguientes pasos:

  1. Guardando el registro de compilación en un archivo ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Busque el texto: warning MS...o la información de advertencia específica: (por ejemplo, la línea 9293) Found conflicts between different versions...y el detalle completo del error de conflicto estará arriba de este mensaje (por ejemplo, la línea 9277)There was a conflicts between... Encuentra el mensaje de error

Visual Studio 2013

Jaider
fuente
Gran sugerencia para buscar 3277 en la salida.
sfuqua
21

Descubrí que (al menos en Visual Studio 2010) necesita establecer la verbosidad de salida en al menos Detallado para poder detectar el problema.

Es posible que mi problema fuera una referencia que anteriormente era una referencia de GAC, pero ese ya no era el caso después de la reinstalación de mi máquina.

ErikHeemskerk
fuente
1
Vaya a Herramientas-> Opciones-> Proyectos y soluciones-> Compilar y ejecutar para configurar la verbosidad de salida.
Farshid
8

Tuve el mismo error y no pude resolverlo con las otras respuestas. Descubrí que podemos "consolidar" los paquetes NuGet.

  1. Haga clic derecho en la solución
  2. Haga clic en Administrar paquetes Nuget
  3. Consolidar pestaña y actualizar a la misma versión.
Villancico
fuente
7

Esta advertencia generada para la versión beta de ASP.NET MVC 4 predeterminada, vea aquí

En cualquier conversión, esta Advertencia puede eliminarse editando manualmente el archivo .csproj para su proyecto.

modificar ........: Referencia Incluir = "System.Net.Http"

para leer ......: Referencia Incluir = "System.Net.Http, Versión = 4.0.0.0"

RouR
fuente
1
Seguí esto y el error ha desaparecido. Aún no sé cómo ni por qué, comencé un proyecto MVC 4 con VS2010 y luego migré en VS2012. Sin embargo, al agregar el atributo de versión, el error desapareció. Gracias
MaiOM
6

Use un lector de dependencia

Usando dep.exe puede enumerar todas las dependencias anidadas de una carpeta completa. Combinado con herramientas Unix como grep o awk, puede ayudarte a resolver tu problema

Encontrar conjuntos a los que se hace referencia en más de una versión

$ 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            

Esta oscura línea de comando ejecuta dep.exe y luego canaliza la salida dos veces para awk a

  • coloque el padre y el hijo en una sola columna (por defecto, cada línea contiene un padre y un hijo para expresar el hecho de que este padre depende de ese hijo)
  • luego haga una especie de 'grupo por' usando una matriz asociativa

Comprender cómo esta asamblea se metió en su contenedor

$ 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 

En este ejemplo, la herramienta le mostrará que System.Web.Http 5.2.3 proviene de su dependencia de FooLib, mientras que la versión 4.0.0 proviene de BarLib.

Entonces tienes la opción entre

  • convencer a los propietarios de las librerías para que usen la misma versión
  • deja de usar uno de ellos
  • Agregar redireccionamientos vinculantes en su archivo de configuración para usar la última versión

Cómo ejecutar estas cosas en Windows

Si usted no tiene un tipo de UNIX que tendrá que descargar uno antes de ser capaz de correr awky grep. Pruebe uno de los siguientes

Manitra Andriamitondra
fuente
4

También tuve este problema y utilicé el consejo de AMissico para descubrir el problema (aunque tuve que establecer el nivel de verbosidad en Detallado.

Sin embargo, el problema fue bastante sencillo después de encontrar al culpable.

Antecedentes: actualicé mi proyecto de VS2008 a VS2010. En VS2008, el marco de destino era 3.5 y cuando lo introduje en VS2010 lo cambié a 4 (Completo). También actualicé algunos componentes de terceros, incluidos los informes de Crystal.

Resultó que la mayoría de las referencias del sistema apuntaban a la versión 4.0.0.0, pero un par no se había cambiado automáticamente (System y System.Web.Services) y todavía estaban mirando 2.0.0.0. Crystal Reports hace referencia a 4.0.0.0, por lo que aquí es donde se producían los conflictos. Simplemente colocando el cursor en la primera biblioteca del Sistema en el explorador de soluciones, bajando el cursor por la lista y buscando referencias a 2.0.0.0, eliminando y volviendo a agregar la nueva versión 4.0.0.0 hizo el truco.

Lo extraño fue que la mayoría de las referencias se habían actualizado correctamente y si no fuera por los informes de Crystal, probablemente nunca me habría dado cuenta ...

Hamiora
fuente
2

Como se mencionó aquí , debe eliminar las referencias no utilizadas y las advertencias desaparecerán.

lex87
fuente
1

ASP.NET build manager está construyendo el sitio web revisando las carpetas alfabéticamente, y para cada carpeta calcula sus dependencias y construye las dependencias primero y luego la carpeta seleccionada.

En este caso, la carpeta problemática que es ~ / Controls, se selecciona para crearse al principio, por una razón aún desconocida, construye algunos de los controles allí como un ensamblaje separado en lugar de dentro del mismo ensamblaje que otros controles (parece que estar conectado al hecho de que algunos controles dependen de otros controles en la misma carpeta).

Luego, la siguiente carpeta que se construye (~ / File-Center / Control) depende de la carpeta raíz ~ / que depende de ~ / Controls, por lo que la carpeta ~ / Controls se vuelve a construir solo esta vez los controles que se separaron a su propio ensamblaje ahora se unen al mismo ensamblaje que otros controles con el ensamblado separado que todavía se hace referencia.

Entonces, en este punto, el ensamblaje 2 (al menos) tiene los mismos controles y la compilación falla.

Aunque todavía no sabemos por qué sucedió esto, pudimos solucionarlo cambiando el nombre de la carpeta Controles a ZControls, de esta manera no se compila antes de ~ / File-Center / Control, solo después y de esta manera se construye como debería.

Mike Yinger
fuente
1

Arreglo rapido:

Haga clic derecho en la solución -> Administrar paquetes NuGet para la solución -> En Consolidar puede ver si se instalaron diferentes versiones del mismo paquete. Desinstale diferentes versiones e instale la última.

JerryGoyal
fuente
1

A veces AutoGenerateBindingRedirectsno es suficiente (incluso con GenerateBindingRedirectsOutputType). Buscar todas las There was a conflictentradas y corregirlas manualmente una por una puede ser tedioso, por lo que escribí un pequeño fragmento de código que analiza la salida del registro y las genera para usted (vuelca 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);

Consejo: use MSBuild Binary and Structured Log Viewer y solo genere redireccionamientos vinculantes para los conflictos en el proyecto que emite la advertencia (es decir, solo pasa esas there was a conflictlíneas al archivo de texto de entrada para el código anterior [ AssemblyConflicts.txt]).

Ohad Schneider
fuente
0

Una forma más sencilla sin sin tener en cuenta las dependencias (internas):

  1. Abra el "Explorador de soluciones".
  2. Haga clic en "Mostrar todos los archivos"
  3. Expandir "Referencias"
  4. Verá una (o más) referencia (s) con un icono ligeramente diferente al resto. Por lo general, es con un cuadro amarillo que le sugiere que tome nota de ello. Solo quítalo.
  5. Agregue la referencia nuevamente y compile su código.
  6. Eso es todo.

En mi caso, hubo un problema con la referencia de MySQL. De alguna manera, podría enumerar tres versiones de este en la lista de todas las referencias disponibles. Seguí los procesos 1 a 6 anteriores y funcionó para mí.

Sukhi
fuente
0

Si tiene un compartidor, elimine toda referencia no utilizada en su solución.

Pascal Carmoni
fuente