Como corrijo o erro de compilação do Visual Studio, "incompatibilidade entre a arquitetura do processador"?

459

Eu sou novo na configuração de projetos no Visual Studio 2010, mas fiz algumas pesquisas e ainda não consigo entender esse problema. Eu tenho uma solução do Visual Studio com uma DLL C ++ referenciando a DLL C #. A DLL do C # faz referência a algumas outras DLLs, algumas dentro do meu projeto e outras externas. Quando tento compilar a DLL C ++, recebo este aviso:

aviso MSB3270: Houve uma incompatibilidade entre a arquitetura do processador do projeto que está sendo criado "MSIL" e a arquitetura do processador da referência "[dll C # interna]", "x86".

Ele me diz para ir ao Gerenciador de Configurações para alinhar minhas arquiteturas. A DLL do C # é configurada com o destino da plataforma x86. Se eu tentar mudar isso para outra coisa, como qualquer CPU, ele se queixa porque uma das DLLs externas de que depende tem o destino da plataforma x86.

Quando olho para o Gerenciador de Configurações, ele mostra a Plataforma para minha DLL de C # como x86 e para meu projeto de C ++ como Win32. Essa parece ser a configuração correta; certamente não quero que o projeto do meu projeto C ++ tenha a plataforma definida como x64, que é a única outra opção apresentada.

O que eu estou fazendo errado aqui?

Paul Eastlund
fonte
Qual é a reclamação, especificamente, quando você a altera para Qualquer CPU?
Lordcheeto
2
Não tenho informações suficientes para fazer uma sugestão informada, mas clique com o botão direito do mouse na sua solução -> Projeto Build Order e verifique se o seu projeto C # está sendo criado antes do projeto C ++. Caso contrário, vá para a guia Dependências e informe ao VS que o projeto C ++ depende do projeto C #.
Lordcheeto
2
Visual Studio é novamente uma porcaria sobre isso. A plataforma na parte superior da minha tela diz x64, mas o aviso diz que o projeto que está sendo construído é "MSIL". Portanto, o Visual Studio está me dizendo que há uma incompatibilidade entre maçãs e laranjas quando não estou usando maçãs. Podemos renomeá-lo para Visual Stupido?
Paul McCarthy
No que me diz respeito, é um erro no Visual Studio. Seleciono x64 como destino da plataforma e isso indica que o projeto está sendo desenvolvido para o MSIL.
Paul McCarthy
A resposta curta é: se seu projeto tiver dependências de x86 ou x64, você não poderá usar Qualquer CPU (que é apenas para aplicativos .NET puros). Então você tem que construir para x64 ou x32, não para qualquer CPU. Isto é derivado da resposta
zar

Respostas:

513

Esse aviso parece ter sido introduzido com o novo Visual Studio 11 Beta e .NET 4.5, embora suponha que isso já fosse possível antes.

Primeiro, é realmente apenas um aviso. Não deve prejudicar nada se você estiver apenas lidando com dependências x86. A Microsoft está apenas tentando avisá-lo quando você declara que seu projeto é compatível com "Qualquer CPU", mas você depende de um projeto ou assembly .dll que é x86 ou x64. Como você possui uma dependência x86, tecnicamente, seu projeto não é compatível com "Qualquer CPU". Para fazer o aviso desaparecer, você deve realmente mudar seu projeto de "Qualquer CPU" para "x86". Isso é muito fácil de fazer, aqui estão os passos.

  1. Vá para o item de menu Build | Configuration Manager.
  2. Encontre seu projeto na lista, em Plataforma, ele diz "Qualquer CPU"
  3. Selecione a opção "Qualquer CPU" na lista suspensa e selecione <New..>
  4. Nessa caixa de diálogo, selecione x86 na lista suspensa "Nova plataforma" e verifique se "Qualquer CPU" está selecionada na lista suspensa "Copiar configurações de".
  5. Hit OK
  6. Você deseja selecionar x86 para as configurações Debug e Release.

Isso fará o aviso desaparecer e também declarará que sua montagem ou projeto não é mais compatível com "Qualquer CPU", mas agora específico para x86. Isso também é aplicável se você estiver criando um projeto de 64 bits com uma dependência x64; você apenas selecionaria x64.

Outra observação: os projetos podem ser compatíveis com "Qualquer CPU", geralmente se forem projetos .NET puros. Esse problema ocorre apenas se você introduzir uma dependência (DLL de terceiros ou seu próprio projeto gerenciado em C ++) que tenha como alvo uma arquitetura de processador específica.

David Sacks
fonte
3
Acabei de instalar o RTW do Visual Studio 2012 e abri uma solução 2010 preexistente e comecei a ver o mesmo aviso, por isso é algo que ainda existe no RTW.
Tod Thomson
4
Dito isto, acho que a resposta de David está correta, esse aviso informa que seu aplicativo realmente não é "AnyCPU"; portanto, você terá problemas quando o implantar na arquitetura errada.
Tod Thomson
6
Muito bem pode machucar algo. Um Qualquer CPU exe será carregado como x64 em um sistema operacional de 64 bits e não poderá carregar DLLs x86. Portanto, se você tem uma dependência de uma plataforma específica, deve configurá-la corretamente.
Yaur
1
O menu Build parece estar ausente no VS C # 2010 Express. Como chego a isso? Eu gostaria que eles não escondessem as coisas.
Xonatron
1
Acabei de descobrir como habilitar o menu de criação no Visual Studio 2010 Express: menu Ferramentas -> Configurações -> selecione 'Configurações de especialistas'
Xonatron
144

Este é um aviso muito teimoso e, embora seja um aviso válido, há alguns casos em que não pode ser resolvido devido ao uso de componentes de terceiros e outros motivos. Eu tenho um problema semelhante, exceto que o aviso é que minha plataforma de projetos é AnyCPU e estou fazendo referência a uma biblioteca MS criada para AMD64. A propósito, isso está no Visual Studio 2010 e parece ter sido apresentado com a instalação do VS2012 e do .Net 4.5.

Como não posso alterar a biblioteca da Microsoft que estou referenciando e como sei que meu ambiente de implantação de destino só será de 64 bits, posso ignorar com segurança esse problema.

E o aviso? A Microsoft postou em resposta a um relatório do Connect que uma opção é desativar esse aviso. Você só deve fazer isso, se estiver muito ciente da arquitetura da sua solução e entender completamente seu destino de implantação e saber que não é realmente um problema fora do ambiente de desenvolvimento.

Você pode editar seu arquivo de projeto e adicionar este grupo de propriedades e configuração para desativar o aviso:

<PropertyGroup>
  <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
Gio Palacino
fonte
1
A única outra referência oficial da Microsoft a esta solução que eu já vi está no arquivo Leiame do Microsoft .NET Framework 4.5 RC . Estranhamente, ele foi removido do arquivo Leia-me do RTM.
10133 JohnC
4
Isso funciona, mas não para uma variação do aviso: "Montagem referenciada ... visa um processador diferente do aplicativo". Seria ótimo se houvesse uma configuração semelhante para este aviso?
Jimmy
6
"minha plataforma de projetos é AnyCPU e estou fazendo referência a uma biblioteca MS criada para AMD64" ... Isso está errado. Como sua implantação de destino é sempre de 64 bits, você pode definir sua plataforma como x64, o que gera um erro mais apropriado se sua suposição de 64 bits for violada e também impedir o aviso.
Ben Voigt
2
@BenVoigt é uma ótima idéia, em teoria, mas o VS, sendo um processo x86, precisa de compilações x86 de controles para executar coisas como o Windows Forms Designer, mesmo que seu aplicativo tenha apenas 64 bits. É uma razão válida, mas lamentável, para usar uma falsa versão "Qualquer CPU".
JRH
1
@ jrh: Em seguida, coloque a GUI em um projeto DLL e crie- o como AnyCPU. O EXE precisa ser marcado com a arquitetura correta para corresponder às dependências nativas. A separação adequada da GUI da lógica percorre um longo caminho (embora ainda tenha seus limites, como quando o código nativo está processando parte da GUI, mas o suporte ao designer é uma causa perdida, a menos que você construa todo o projeto para ambos x86 e x64)
Ben Voigt
61

Uma boa regra geral é "DLLs abertas, EXEs fechadas", ou seja:

  • O EXE tem como alvo o sistema operacional, especificando x86 ou x64.
  • As DLLs são deixadas em aberto (ou seja, AnyCPU) para que possam ser instanciadas em um processo de 32 ou 64 bits.

Quando você cria um EXE como AnyCPU, tudo o que você está fazendo é adiar a decisão sobre qual processo usar para o sistema operacional, o que levará o EXE ao seu gosto. Ou seja, um sistema operacional x64 criará um processo de 64 bits, um sistema operacional x86 criará um processo de 32 bits.

Criar DLLs como AnyCPU as torna compatíveis com qualquer um dos processos.

Para mais informações sobre as sutilezas do carregamento da montagem, consulte aqui . O resumo executivo lê algo como:

  • AnyCPU - carrega como montagem x64 ou x86, dependendo do processo de chamada
  • x86 - carrega como montagem x86; não será carregado de um processo x64
  • x64 - carrega como montagem x64; não será carregado de um processo x86
Gustavo Mori
fonte
4
Esta regra faz sentido para mim. Mas considere a seguinte situação: Native.dll (x64) usado pelo NetA.dll (qualquer CPU) usado pelo NetB.dll (qualquer CPU) usado pelo App1.exe (x64). Não há nenhum problema real aqui, mas a compilação do NetA.dll me dá o aviso. OK, como esse assembly depende diretamente do Native.dll, eu também poderia marcá-lo como x64. Mas, em seguida, compilar NetB.dll reclama. Desejo manter o NetB.dll como "Qualquer CPU" porque é um assembly comum usado em um aplicativo diferente de ponto de rede puro. Concluo que minha única opção é suprimir / ignorar o aviso. Sim?
Steve Robbins
2
Devido à dependência do Native.dll, toda a linhagem de aplicativo / montagem agora é x64, independentemente de você suprimir o aviso ou não. Enquanto a supressão funciona no seu cenário, situações estranhas podem surgir no futuro. Por exemplo, 1) o NetB de montagem é usado em um ambiente x86, em que o Nativex64 não carrega, ou 2) seu cliente deseja uma versão x86 do App1.exe e você compila com satisfação, pois o NetB está marcado como qualquer CPU, mas novamente, Nativex64 no topo da pilha não será carregada
Gustavo Mori
Embora a regra de Gustavo seja um bom princípio, ela não pode ser usada para o problema específico solicitado nesta pergunta, pois o projeto já depende de uma montagem de terceiros que não seguiu a regra (é x86, não AnyCPU). Portanto, desde que a dependência exista, toda a cadeia de projetos deve ter como alvo x86 e nada mais.
David Burg
23

A DLL do C # é configurada com o destino da plataforma x86

Qual é o tipo de problema, uma DLL não consegue realmente escolher qual será o testemunho do processo. Isso é inteiramente determinado pelo projeto EXE, que é o primeiro assembly que é carregado, de modo que a configuração de destino da Plataforma é a que conta e define o status do processo.

As DLLs não têm escolha, elas precisam ser compatíveis com a testemunha do processo. Se não estiverem, você receberá um grande Kaboom com uma BadImageFormatException quando seu código tentar usá-los.

Portanto, uma boa seleção para as DLLs é AnyCPU, portanto elas funcionam de qualquer maneira. Isso faz muito sentido para C # DLLs, eles fazem o trabalho de qualquer maneira. Mas, claro, não a DLL de modo misto C ++ / CLI, ela contém código não gerenciado que só funciona bem quando o processo é executado no modo de 32 bits. Você pode fazer o sistema de compilação gerar avisos sobre isso. Qual é exatamente o que você conseguiu. Apenas avisos, ele ainda cria corretamente.

Apenas aponte o problema. Defina o destino da plataforma do projeto EXE como x86, ele não funcionará com nenhuma outra configuração. E apenas mantenha todos os projetos DLL em AnyCPU.

Hans Passant
fonte
1
Portanto, para esclarecer: não estou criando o EXE, estou criando uma DLL para ser executada com o EXE de outra pessoa. Alterar o destino da plataforma das DLLs do C # para Qualquer CPU não elimina o aviso. Gostaria de saber se este é um caso de connect.microsoft.com/VisualStudio/feedback/details/728901/… - eu ignoraria o aviso propriamente dito, mas na verdade o EXE é capaz de carregar a DLL do C #, mas não a DLL do C ++ então eu acho que isso é um problema real.
Paul Eastlund
Você está de fato usando o VS2010? Também não ficou claro que você não pôde carregar a DLL C ++ / CLI. Qual é o diagnóstico? Atualize suas perguntas com essas informações essenciais.
Hans Passant
Não havia postado sobre a falha no carregamento, porque eu não tinha 100% de certeza de que estava conectado e, após uma depuração adicional, não foi. Estou usando o VS2010. Texto da pergunta atualizado. Muito triste de confusão
Paul Eastlund
1
Você não documentou nenhum tipo de erro ou exceção relacionado ao carregamento da DLL. Não posso ajudá-lo se você não me contar o que sabe. Boa sorte com isso.
18712 Hans Passant
5

Eu estava recebendo o mesmo aviso que fiz isso:

  1. descarregar projeto
  2. editar propriedades do projeto, por exemplo, .csproj
  3. adicione a seguinte tag:

    <PropertyGroup>
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
            None
        </ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
  4. Recarregar o projeto

yogeshwar gutte
fonte
2
Isso não está resolvendo o problema. Está apenas desativando o aviso para o projeto em particular. Mas, em alguns casos, acho uma solução válida. Obrigado!
minúsculo
4

Eu tive esse problema hoje e apenas a aparência das configurações de construção no Visual Studio não estava ajudando, pois mostrava Qualquer CPU para o projeto que não estava sendo construído e o projeto referenciado.

Procurei no csproj do projeto referenciado e encontrei o seguinte:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>

De alguma forma, este PlatformTarget foi adicionado no meio de uma alteração de configuração e o IDE não pareceu vê-lo.

A remoção desta linha do projeto referenciado resolveu meu problema.

JBourne
fonte
Levei um dia inteiro para descobrir isso. Muito obrigado! :)
SohamC
3

Se a DLL do C # tiver dependências baseadas em x86, a própria DLL precisará ser x86. Eu realmente não vejo uma maneira de contornar isso. O VS reclama de alterá-lo para (por exemplo) x64 porque um executável de 64 bits não pode carregar bibliotecas de 32 bits.

Estou um pouco confuso sobre a configuração do projeto C ++. A mensagem de aviso fornecida para a compilação sugere que ela foi direcionada para AnyCPU, porque relatou a plataforma que foi direcionada para [MSIL], mas você indicou que a configuração do projeto era realmente o Win32. Um aplicativo Win32 nativo não deve envolver o MSIL - embora provavelmente precise ter o suporte ao CLR ativado se estiver interagindo com uma biblioteca C #. Então, acho que existem algumas lacunas no lado da informação.

Eu poderia respeitosamente pedir para você revisar e postar um pouco mais detalhadamente a configuração exata dos projetos e como eles estão inter-relacionados? Fique feliz em ajudar ainda mais, se possível.

David W
fonte
3

Além de resposta David Sacks, você também pode precisar de ir para o Buildguia do Project Propertiese conjunto Platform Targetpara x86para o projeto que está lhe dando esses avisos. Embora você possa esperar que seja, essa configuração não parece estar perfeitamente sincronizada com a configuração no gerenciador de configuração.

Dave Cousineau
fonte
2

Para projetos em C #, o destino do x86 faz o que parece. Ele diz que esse assembly suporta apenas arquiteturas x86. Da mesma forma para x64. Qualquer CPU, por outro lado, diz que não ligo para qual arquitetura, eu apoio ambos. Portanto, as próximas 2 perguntas são (1) qual é a configuração do executável que usa essas DLLs? e (2) qual é a testemunhado seu sistema operacional / computador? A razão pela qual pergunto é porque, se o seu executável é compilado para ser executado em 64 bits, ele PRECISA de todas as dependências para poder executar também no modo de 64 bits. Seu assembly Any CPU deve poder ser carregado, mas talvez esteja referenciando alguma outra dependência que só pode ser executada na configuração x86. Verifique todas as dependências e dependências de dependências para garantir que tudo seja "Qualquer CPU" ou "x64" se você planeja executar o executável no modo de 64 bits. Caso contrário, você terá problemas.

De várias maneiras, o Visual Studio não facilita a compilação de uma mistura de Qualquer CPU e vários conjuntos dependentes da arquitetura. É possível, mas geralmente exige que um assembly que seria "Qualquer CPU" precise ser compilado separadamente para x86 e x64, porque alguma dependência de dependência em algum lugar tem duas versões.

Jonathan DeCarlo
fonte
A configuração do executável é pertinente, pois estou recebendo uma falha apenas ao tentar criar as DLLs? (Porém, é x86.) Meu computador é x64.
Paul Eastlund
2
É o executável que determina qual testemunha será usada. Se o executável estiver sendo executado como x64, qualquer coisa que carregar (direta ou indiretamente) deverá ser x64 ou Qualquer CPU. Se o executável estiver sendo executado como x86, qualquer coisa que seja carregada (direta ou indiretamente) deverá ser x86 ou Qualquer CPU.
Jonathan DeCarlo
1

Eu já tive um problema semelhante antes, especificamente ao adicionar uma solução de teste a uma solução x64 existente, como o SharePoint. No meu caso, parece ter a ver com o fato de que certos modelos de projeto são adicionados como determinadas plataformas por padrão.

Aqui está a solução que geralmente funciona para mim: defina tudo para a plataforma correta no Gerenciador de Configurações (a lista suspensa de configuração ativa, diz Debug normalmente, é uma boa maneira de acessá-la) e a plataforma do projeto (nas propriedades do projeto) e, em seguida, construir e, em seguida, configure tudo de volta para AnyCPU. Às vezes, tenho que remover e adicionar novamente algumas dependências (DLLs nas propriedades de cada projeto) e às vezes o "Executar testes no processo de 32 ou 64 bits" (clique duas vezes em Local.testsettings e vá para Hosts) precisa ser alterado.

Parece-me que isso é apenas definir algo, em seguida, defini-lo de volta, mas provavelmente há mais acontecendo nos bastidores que eu não estou vendo. No entanto, funcionou bastante consistente para mim no passado.

ssamuel
fonte
1

Para o meu projeto, tenho um requisito para poder construir para x86 e x64. O problema é que, sempre que você adiciona referências ao usar uma, ela se queixa quando você cria a outra.

Minha solução é editar manualmente os arquivos * .csproj para que linhas como estas:

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86"/>

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64"/>

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"/>

seja alterado para isso:

<Reference Include="MyLibrary.MyNamespace, Version=1.0.0.0, Culture=neutral"/>
Thick_propheT
fonte
1

Eu tive um problema semelhante que foi causado pela DLL de teste do MS UNIT. Meu aplicativo WPF foi compilado como x86, mas DLL de teste de unidade (arquivo EXE referido) como "Qualquer CPU". Mudei a DLL de teste de unidade para ser compilada para x86 (o mesmo que EXE) e ela foi novamente restaurada.

user1257110
fonte
0

Deve haver uma maneira de criar um .NET EXE / DLL AnyCPU e quaisquer DLLs não gerenciadas dos quais depende, compilados com x86 e x64, ambos agrupados talvez com nomes de arquivos diferentes e, em seguida, o módulo .NET carregando dinamicamente o correto com base no tempo de execução arquitetura do processador. Isso tornaria o AnyCPU poderoso. Se a DLL do C ++ suporta apenas x86 ou x64, é claro que o AnyCPU não faz sentido. Mas a ideia de agrupar as duas coisas que ainda tenho que ver implementadas, já que o gerenciador de configuração nem fornece um meio de construir o mesmo projeto duas vezes com uma configuração / plataforma diferente para a agregação múltipla, permitindo que AnyCPU ou mesmo outros conceitos como qualquer configuração sejam possíveis.

Gregory Morse
fonte
2
bem-vindo ao stackoverflow! você pode tentar focar / reformatar um pouco essa resposta?
Corley Brigman
Parece que seria uma boa pergunta, uma postagem no blog ou uma solicitação de recurso no Connect ... na verdade, não responde a esta.
Ben Voigt
0

Eu tive um aviso muito semelhante na minha compilação. Meus projetos foram definidos para atingir o .NET 4.5, no servidor de compilação o Windows 8.1 SDK (para .NET 4.5.1) foi instalado. Depois de atualizar meus projetos para o .NET 4.5.1 (não era um problema para mim, era para um aplicativo completamente novo), não recebi mais o aviso ...

NicoCV
fonte
0

Resolvi esse aviso alterando o "Gerenciador de Configurações" para Liberar (plataforma mista).

Edu Pelais
fonte
0

Recebi esse aviso no Visual Studio 2012 ao compilar uma tarefa de script de pipeline do SQL Server 2012 SP1 SSIS - até instalar o SQL Server 2012 SP2.

cdonner
fonte
0

Eu tive o mesmo problema com a conexão de abertura do SQLite e, usando o Nuget e instalando o componente usado no projeto (SQLite), foi corrigido! tente instalar seu componente dessa maneira e verifique o resultado

StudioX
fonte