Resolvendo MSB3247 - conflitos encontrados entre versões diferentes do mesmo assembly dependente

427

Uma solução .NET 3.5 terminou com esse aviso ao compilar com o msbuild.

Às vezes, o NDepend pode ajudar, mas nesse caso não fornece mais detalhes. Como Bob , acabei tendo que recorrer à abertura de cada assembly no ILDASM até encontrar o que estava fazendo referência a uma versão mais antiga do assembly dependente.

Tentei usar o MSBUILD do VS 2010 Beta 2 (como o artigo do Connect indicou que isso foi corrigido na próxima versão do CLR), mas também não forneceu mais detalhes (talvez corrigido após o Beta 2)

Existe uma abordagem melhor (mais automatizada)?

David Gardiner
fonte
2
No meu caso, eu apenas tive que me certificar de que todos os projetos da solução estavam executando a mesma versão dos pacotes nuget (pode simplesmente atualizar todos para a versão mais recente).
Michael

Respostas:

576

Altere a "verbosidade de saída da compilação do projeto MSBuild" para "Detalhada" ou acima. Para fazer isso, execute as seguintes etapas:

  1. Abra a caixa de diálogo Opções ( Ferramentas -> Opções ... ).
  2. Na árvore esquerda, selecione o nó Projetos e soluções e, em seguida, selecione Compilar e executar .
    • Nota: se esse nó não aparecer, verifique se a caixa de seleção na parte inferior da caixa de diálogo Mostrar todas as configurações está marcada.
  3. Na página de ferramentas / opções exibida, defina o nível de verbosidade de saída da compilação do projeto MSBuild para a configuração apropriada, dependendo da sua versão:

  4. Crie o projeto e procure na janela de saída.

Confira as mensagens do MSBuild. A ResolveAssemblyReferencestarefa, da qual o MSB3247 se origina, deve ajudá-lo a depurar esse problema específico.

Meu caso específico foi uma referência incorreta ao SqlServerCe. Ver abaixo. Eu tinha dois projetos referenciando duas versões diferentes do SqlServerCe. Fui ao projeto com a versão mais antiga, removi a referência e adicionei a referência correta.

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.

Você não precisa abrir cada montagem para determinar as versões de montagens referenciadas.

  • Você pode verificar as propriedades de cada referência.
  • Abra as propriedades do projeto e verifique as versões da seção Referências.
  • Abra os projetos com um editor de texto.
  • Use .Net Reflector.
AMissico
fonte
5
Suas soluções me parecem boas, no entanto, não acho que seja sempre útil usar a seção Referências para visualizar os números de versão. Eu sempre vi o VS "mentir" para mim sobre qual versão está sendo usada versus qual versão é realmente mencionada no arquivo .csproj.
David Gardiner
5
@ David Gardiner - Eu concordo com a sua declaração "mentirosa" ao usar projetos C #. Na minha experiência, projetos C # podem ficar confusos com relação à versão referenciada e à versão real compilada / vinculada. Quando isso acontece, limpo a solução, excluo manualmente as pastas bin e obj e excluo os assemblies temporários do projeto em% APPDATA%. Uma solução de reconstrução geralmente resolve o problema. (VB raramente sofre com esse problema específico.)
AMissico
54
ganhar por dizer às pessoas para realmente usar a janela Saída. A compilação é muito mais do que a janela Lista de erros do F5 +.
JJS
2
Como ErikHeemskerk mencionou em sua resposta, no Visual Studio 2010, você precisará definir a verbosidade de saída como detalhada para ver a saída de ResolveAssemblyReferences.
Robin Clowers
12
Dica: para encontrar o local exato na saída detalhada da compilação, copie o texto em um editor de texto, procure "Conflitos encontrados entre versões diferentes do mesmo assembly dependente".
Contango 21/09
133

Mike Hadlow postou um pequeno aplicativo de console chamado AsmSpy que lista bastante as referências de cada assembly:

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

Essa é uma maneira muito mais rápida de chegar ao final do aviso MSB3247, do que depender da saída do MSBuild.

Noel Abrahams
fonte
1
O AsmSpy é incrível, basta lembrar que você está procurando as referências a DLLs de terceiros com versões incompatíveis. Geralmente, versões incompatíveis nas referências às bibliotecas padrão não causam esses avisos (e você os verá muito).
9788 Toddyson
Esta é uma excelente ferramenta que me ajudou a resolver meu problema imediatamente. No meu caso, no entanto, não eram exatamente DLLs de terceiros, mas referências ao System.Management.Automation.dll que tinha referências diferentes ao mscorlib.dll.
22612 Chris Gillum
A ferramenta é boa, no entanto, não funciona em todas as circunstâncias. Pelo menos para um projeto .NET 4.5, ele não mostrou as versões de referências em colisão para mim. A saída do msbuild nomeia as DLLs em questão com caminhos e tudo.
Twomm
11
Obrigado pelas palavras gentis caras :)
Mike Hadlow
Você acabou de me salvar algumas horas de trabalho! Ajudou a ler a saída detalhada, mas depois que o fiz foi fácil verificar novamente com sua ferramenta.
Norman H
22

Em algum momento a resposta do @AMissico não é suficiente. No meu caso, como não encontrei o erro nas janelas Saída, decidi criar um arquivo de log e analisá-lo, executando as seguintes etapas:

  1. Salvando o log de compilação em um arquivo ... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Encontre o texto: warning MS...ou as informações de aviso específicas: (por exemplo, linha 9293) Found conflicts between different versions...e os detalhes completos do erro de conflito estarão acima desta mensagem (por exemplo, linha 9277)There was a conflicts between... Encontre a mensagem de erro

Visual Studio 2013

Jaider
fonte
Ótima dica para procurar 3277 na saída.
precisa saber é o seguinte
21

Descobri que (pelo menos no Visual Studio 2010) você precisa definir a verbosidade de saída como pelo menos Detalhada para poder detectar o problema.

Pode ser que meu problema tenha sido uma referência anterior ao GAC, mas esse não era mais o caso após a reinstalação da máquina.

ErikHeemskerk
fonte
1
Vá em Ferramentas-> Opções-> Projetos e soluções-> Compilar e executar para definir a verbosidade da saída.
Farshid
8

Eu tive o mesmo erro e não consegui descobrir com as outras respostas. Descobri que podemos "consolidar" pacotes NuGet.

  1. Clique com o botão direito na solução
  2. Clique em Gerenciar pacotes Nuget
  3. Consolidar guia e atualizar para a mesma versão.
Carol
fonte
7

Este aviso gerado para o ASP.NET MVC 4 beta padrão, consulte aqui

Em, qualquer conversão desse aviso pode ser eliminada editando manualmente o arquivo .csproj para o seu projeto.

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

to read ......: Reference Include = "System.Net.Http, Versão = 4.0.0.0"

RouR
fonte
1
Eu segui isso e o erro desapareceu. Ainda não sei como ou por quê, iniciei um projeto MVC 4 com o VS2010 e depois migrei no VS2012. No entanto, ao adicionar o atributo version, o erro desapareceu. Graças
MaiOM
6

Use um leitor de dependência

Usando dep.exe você pode listar todas as dependências aninhadas de uma pasta inteira. Combinado com ferramentas unix como grep ou awk, ele pode ajudá-lo a resolver seu problema

Localizando montagens sendo referenciadas em mais de uma versão

$ 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            

Essa linha de comando obscura executa dep.exe e envia a saída duas vezes para ativar

  • coloque o pai e o filho em uma única coluna (por padrão, cada linha contém um pai e um filho para expressar o fato de que esse pai depende desse filho)
  • então faça um tipo de 'agrupar' usando uma matriz associativa

Entendendo como essa montagem foi puxada para sua lixeira

$ 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 

Neste exemplo, a ferramenta mostraria que o System.Web.Http 5.2.3 vem da sua dependência do FooLib, enquanto a versão 4.0.0 vem do BarLib.

Então você tem a escolha entre

  • convencendo os proprietários das bibliotecas a usar a mesma versão
  • pare de usar um deles
  • adicionando redirecionamentos de ligação no seu arquivo de configuração para usar a versão mais recente

Como executar essas coisas no Windows

Se você não tem um tipo de shell unix você precisará baixar um antes de ser capaz de executar awke grep. Tente um dos seguintes

Manitra Andriamitondra
fonte
4

Eu também tive esse problema e usei o conselho de AMissico para descobrir o problema (embora tenha que definir o nível de verbosidade como Detalhado.

O problema foi bastante simples, depois de encontrar o culpado.

Antecedentes: atualizei meu projeto do VS2008 para o VS2010. No VS2008, a estrutura de destino era 3,5 e, quando a trouxe para o VS2010, mudei para 4 (Completo). Também atualizei alguns componentes de terceiros, incluindo Crystal Reports.

Ele resultou na maioria das referências do sistema, apontando para a versão 4.0.0.0, mas algumas não foram alteradas automaticamente (System e System.Web.Services) e ainda estavam na 2.0.0.0. O Crystal Reports está fazendo referência à 4.0.0.0 e, portanto, era nesse ponto que os conflitos estavam ocorrendo. Basta colocar o cursor na primeira biblioteca do sistema no gerenciador de soluções, percorrer o cursor da lista e procurar por referências ao 2.0.0.0, remover e adicionar novamente a versão mais recente do 4.0.0.0.

O estranho era que a maioria das referências havia sido atualizada corretamente e, se não fosse pelos relatórios do Crystal, eu provavelmente nunca teria notado ...

Hamiora
fonte
2

Como mencionado aqui , você precisa remover as referências não utilizadas e os avisos serão exibidos.

lex87
fonte
1

O gerenciador de compilação do ASP.NET está construindo o site, percorrendo as pastas em ordem alfabética e, para cada pasta, descobre as dependências e cria as dependências primeiro e depois a pasta selecionada.

Nesse caso, a pasta problemática que é ~ / Controls é selecionada para ser criada no início, por um motivo ainda desconhecido, ela cria alguns dos controles lá como um assembly separado, em vez de dentro do mesmo assembly que outros controles (parece estar conectado ao fato de que alguns controles dependem de outros na mesma pasta).

Em seguida, a próxima pasta criada (~ / Centro de Arquivos / Controle) depende da pasta raiz ~ / que depende de ~ / Controls, portanto, a pasta ~ / Controls está sendo criada novamente somente desta vez os controles que foram separados Agora, a sua própria montagem agora está unida à mesma montagem que outros controles com a montagem separada ainda sendo referenciada.

Portanto, neste ponto, a montagem 2 (pelo menos) tem os mesmos controles e a compilação falha.

Embora ainda não saibamos por que isso aconteceu, fomos capazes de contorná-la alterando o nome da pasta Controls para ZControls, dessa forma, ela não foi criada antes do ~ / File-Center / Control, somente depois e dessa forma. Como deveria.

Mike Yinger
fonte
1

Conserto rápido:

Clique com o botão direito do mouse em solução -> Gerenciar pacotes NuGet para solução -> em Consolidar, você pode ver se há versões diferentes do mesmo pacote instaladas. Desinstale versões diferentes e instale a mais recente.

JerryGoyal
fonte
1

Às vezes AutoGenerateBindingRedirectsnão é suficiente (mesmo com GenerateBindingRedirectsOutputType). Procurar todas as There was a conflictentradas e corrigi-las manualmente uma a uma pode ser entediante, por isso escrevi um pequeno pedaço de código que analisa a saída do log e as gera para você (despeja para 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);

Dica: use Visualizador de Log Estruturado e Binário do MSBuild gere apenas redirecionamentos de ligação para os conflitos no projeto que emite o aviso (ou seja, apenas passe essas there was a conflictlinhas para o arquivo de texto de entrada para o código acima [ AssemblyConflicts.txt]).

Ohad Schneider
fonte
0

Uma maneira mais simples, sem que se leve em consideração as dependências (internas):

  1. Abra o "Gerenciador de Soluções".
  2. Clique em "Mostrar todos os arquivos"
  3. Expandir "Referências"
  4. Você verá uma (ou mais) referência (s) com ícone ligeiramente diferente do resto. Normalmente, é com uma caixa amarela, sugerindo que você tome nota disso. Apenas remova-o.
  5. Adicione a referência novamente e compile seu código.
  6. Isso é tudo.

No meu caso, houve um problema com a referência do MySQL. De alguma forma, eu poderia listar três versões dele na lista de todas as referências disponíveis. Eu segui o processo 1 a 6 acima e funcionou para mim.

Sukhi
fonte
0

Se você tiver um afiador novamente, remova todas as referências não utilizadas na sua solução.

Pascal Carmoni
fonte