Condicionalmente use referência de 32/64 bits ao criar no Visual Studio

Eu tenho um projeto que constrói em 32/64-bit e tem dependencies de 32/64-bit correspondentes. Eu quero ser capaz de alternar configurações e ter a referência correta usada, mas eu não sei como dizer ao Visual Studio para usar a dependência apropriada de arquitetura.

Talvez eu esteja indo sobre isso da maneira errada, mas eu quero ser capaz de alternar entre x86 e x64 na lista suspensa de configuração, e ter a DLL referenciada como a melhor definição.

Aqui está o que eu fiz em um projeto anterior, que exigirá a edição manual do (s) arquivo (s) .csproj. Você também precisa de diretórios separados para os diferentes binários, idealmente irmãos uns dos outros, e com o mesmo nome da plataforma que você está almejando.

Depois de adicionar as referências de uma única plataforma ao projeto, abra o .csproj em um editor de texto. Antes do primeiro elemento dentro do elemento , adicione o seguinte código, que ajudará a determinar em qual plataforma você está executando (e compilando).

   x86 AMD64  

Em seguida, para as referências específicas da sua plataforma, você faz alterações como as seguintes:

   False ..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.dll   False ..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.Codecs.dll   False ..\..\Lib\Leadtools\$(CurrentPlatform)\Leadtools.ImageProcessing.Core.dll       

Observe o uso da propriedade $(CurrentPlatform) , que definimos acima. Você poderia, em vez disso, usar condicionais para quais conjuntos include para qual plataforma. Você também pode precisar:

  • Substitua o $(PROCESSOR_ARCHITEW6432) e $(PROCESSOR_ARCHITECTURE) por $(Platform) para considerar SOMENTE a plataforma de destino dos projetos
  • Altere a lógica de determinação de plataforma para que seja adequada à máquina atual, para que você não esteja criando / referenciando um binário de 64 bits para executar em uma plataforma de 32 bits.

Eu escrevi isso originalmente para um Wiki interno no trabalho, mas eu o modifiquei e publiquei o processo completo no meu blog , se você estiver interessado nas instruções detalhadas passo a passo.

AFAIK, se o seu projeto exigir referências específicas de 32 bits ou 64 bits (ou seja, montagens de interoperabilidade COM), e você não tiver interesse em editar manualmente o arquivo .csproj, será necessário criar 32 bits separados e Projetos de 64 bits.

Devo observar que a seguinte solução não foi testada, mas deve funcionar. Se você estiver disposto a editar manualmente o arquivo .csproj, será possível obter o resultado desejado com um único projeto. O arquivo .csproj é apenas um script do MSBuild, portanto, para uma referência completa, veja aqui . Depois de abrir o arquivo .csproj em um editor, localize os elementos . Você deve ser capaz de dividir esses elementos em três grupos de itens distintos: referências que não são específicas da plataforma, referências específicas do x86 e referências específicas do x64.

Aqui está um exemplo que assume que seu projeto está configurado com plataformas de destino chamadas “x86” e “x64”

          ..\..\lib\x86\MyComAssembly.Interop.dll       ..\..\lib\x64\MyComAssembly.Interop.dll    

Agora, quando você definir sua configuração de projeto / solução para segmentar a plataforma x86 ou x64, ela deverá include as referências apropriadas em cada caso. Claro, você precisará brincar com os elementos . Você pode até mesmo configurar projetos fictícios onde você adiciona as referências x86 e x64 e, em seguida, basta copiar os elementos necessários desses arquivos de projeto fictícios para o seu arquivo de projeto “real”.

Editar 1
Aqui está um link para os itens comuns do projeto MSBuild, que eu acidentalmente deixei de fora da postagem original: http://msdn.microsoft.com/en-us/library/bb629388.aspx

Você pode usar uma condição para um ItemGroup para as referências de dll no arquivo de projeto.
Isso fará com que o visual studio volte a verificar a condição e as referências sempre que você alterar a configuração ativa.
Basta adicionar uma condição para cada configuração.

Exemplo:

    ..\DLLName.dll   {AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT} MyOtherProject   

Estou fazendo referência às DLLs x86, localizadas em eg \ component \ v3_NET4, no meu projeto. DLLs específicas para x86 / x64 estão localizadas em sub-pastas denominadas “x86” e “x64” resp.

Então eu estou usando um script de pré-compilation que copia DLLs apropriadas (x86 / x64) para a pasta referenciada, com base em $ (PlatformName).

 xcopy /s /e /y "$(SolutionDir)..\component\v3_NET4\$(PlatformName)\*" "$(SolutionDir)..\component\v3_NET4" 

Funciona para mim.

Eu enfrentei o mesmo problema e passei bastante tempo procurando por uma solução decente. A maioria das pessoas oferece edição manual de arquivos de solução do Visual Studio, o que é bastante entediante, propenso a erros e confuso ao explorar esses arquivos editados posteriormente na GUI do Visual Studio. Quando eu já desisti, a solução surgiu sozinha. É muito semelhante ao que Micke recomenda em sua resposta acima.

No gerenciador de contas, criei dois destinos de compilation separados para as plataformas x86 e x64, como de costume. Em seguida, adicionei uma referência ao assembly x86 ao meu projeto. Neste ponto, acreditei que o projeto está configurado apenas para a compilation x86 e nunca será construído para a configuração x64, a menos que eu faça a edição manual conforme sugerido por Hugo acima.

Depois de um tempo, acabei esquecendo a limitação e acidentalmente comecei a construir x64. Claro, a construção falhou. Mas importante foi a mensagem de erro que recebi. Mensagem de erro informava que o assembly nomeado exatamente como meu assembly x86 referenciado está faltando na pasta destinada como destino de compilation x64 para minha solução.

Tendo notado isso, copiei manualmente o assembly x64 adequado para esse diretório. Glória! Minha compilation x64 foi milagrosamente bem-sucedida com assembly adequada encontrada e vinculada implicitamente. Foi questão de minutos para modificar minha solução para definir um diretório de destino de compilation para o assembly x64 para essa pasta. Após essas etapas, a solução é criada automaticamente para x86 e x64 sem qualquer edição manual dos arquivos do MSBuild.

Resumindo:

  1. Crie alvos x86 e x64 em um único projeto
  2. Adicione todas as referências de projeto adequadas aos assemblies x86
  3. Definir um diretório de destino de compilation comum para todos os assemblies x64
  4. Caso você tenha pronto x64 assemblies, basta copiá-los uma vez em seu diretório de destino x64 build

Após a conclusão dessas etapas, sua solução será construída adequadamente para configurações x86 e x64.

Isso funcionou para mim no projeto Visual Studio 2010 .NET 4.0 C #. Evidentemente, esse é um tipo de comportamento interno não documentado do Visual Studio, que pode estar sujeito a alterações nas versões 2012, 2013 e 2015. Se alguém tentar em outras versões, compartilhe sua experiência.

Uma compilation .Net com dependencies x86 / x64

Enquanto todas as outras respostas dão a você uma solução para fazer Builds diferentes de acordo com a plataforma, dou a você a opção de ter apenas a configuração “AnyCPU” e fazer uma compilation que funcione com suas dlls x86 e x64.

Você tem que escrever algum código de encanamento para isso. Eu não consegui fazer isso funcionar com app.config. Se alguém souber uma maneira de resolvê-lo via app.config, eu realmente gostaria de saber.

Resolução de corrigir x86 / x64-dlls em tempo de execução

Passos:

  1. Use AnyCPU no csproj
  2. Decida se você faz referência apenas às dlls x86 ou x64 em seus csprojs. Adapte as configurações do UnitTests às configurações de arquitetura escolhidas. É importante para depurar / executar os testes dentro do VisualStudio.
  3. Em propriedades de referência, defina Copy Local & Specific Version para false
  4. Livre-se dos avisos de arquitetura adicionando esta linha ao primeiro PropertyGroup em todos os seus arquivos csproj nos quais você faz referência a x86 / x64: None
  5. Adicione este script postbuild ao seu projeto de boot, use e modifique os caminhos deste script sp que copia todos os seus x86 / x64 dlls em subpastas correspondentes de sua construção bin \ x86 \ bin \ x64 \

    xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86 xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64

    -> Quando você iniciaria a aplicação agora, você obtém uma exceção que a assembly não pôde ser encontrada.

  6. Registre o evento AssemblyResolve logo no início do ponto de input do seu aplicativo

     AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency; 

    com este método:

     ///  /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve ///  /// The app domain /// The resolve event args /// The architecture dependent assembly public static Assembly TryResolveArchitectureDependency(object sender, ResolveEventArgs resolveEventArgs) { var dllName = resolveEventArgs.Name.Substring(0, resolveEventArgs.Name.IndexOf(",")); var anyCpuAssemblyPath = $".\\{dllName}.dll"; var architectureName = System.Environment.Is64BitProcess ? "x64" : "x86"; var assemblyPath = $".\\{architectureName}\\{dllName}.dll"; if (File.Exists(assemblyPath)) { return Assembly.LoadFrom(assemblyPath); } return null; } 
  7. Se você tiver testes de unidade, faça um TestClass com um Method que tenha um AssemblyInitializeAttribute e também registre o TryResolveArchitectureDependency-Handler acima. (Isso não será executado às vezes se você executar testes únicos no Visual Studio, as referências serão resolvidas não a partir do escaninho UnitTest. Portanto, a decisão na etapa 2 é importante.)

Benefícios:

  • Uma instalação / construção para ambas as plataformas

Inconvenientes: – Nenhum erro em tempo de compilation quando dlls x86 / x64 não correspondem. – Você ainda deve executar o teste nos dois modos!

Opcionalmente, crie um segundo executável exclusivo para a arquitetura x64 com o Corflags.exe no script postbuild

Outras variantes a serem testadas: – Você não precisaria do manipulador de events AssemblyResolve se garantir que as dlls sejam copiadas na sua pasta binária no início (Evaluate Process architecture -> mova dlls correspondentes de x64 / x86 para a pasta bin e vice-versa). – No Installer, avalie a arquitetura e exclua os binários para uma arquitetura incorreta e mova os da direita para a pasta bin.