Sim, você pode direcionar tanto x86 quanto x64 com o mesmo código base no mesmo projeto. Em geral, as coisas simplesmente funcionarão se você criar as configurações de solução certas no VS.NET (embora P / Invoke para DLLs totalmente não gerenciadas provavelmente exija algum código condicional): os itens que descobri que requerem atenção especial são:
- Referências a assemblies gerenciados externos com o mesmo nome, mas seu próprio número de bits específico (isso também se aplica a assemblies de interoperabilidade COM)
- O pacote MSI (que, como já foi observado, precisará ter como alvo x86 ou x64)
- Quaisquer ações baseadas em classes do instalador .NET personalizadas em seu pacote MSI
O problema de referência do assembly não pode ser resolvido inteiramente no VS.NET, pois ele só permitirá que você adicione uma referência com um determinado nome a um projeto uma vez. Para contornar isso, edite seu arquivo de projeto manualmente (no VS, clique com o botão direito do mouse no arquivo de projeto no Solution Explorer, selecione Unload Project, clique com o botão direito novamente e selecione Edit). Depois de adicionar uma referência a, digamos, a versão x86 de um assembly, seu arquivo de projeto conterá algo como:
<Reference Include="Filename, ..., processorArchitecture=x86">
<HintPath>C:\path\to\x86\DLL</HintPath>
</Reference>
Envolva essa tag de referência dentro de uma tag ItemGroup indicando a configuração da solução à qual se aplica, por exemplo:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<Reference ...>....</Reference>
</ItemGroup>
Em seguida, copie e cole a tag ItemGroup inteira e edite-a para conter os detalhes de sua DLL de 64 bits, por exemplo:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<Reference Include="Filename, ..., processorArchitecture=AMD64">
<HintPath>C:\path\to\x64\DLL</HintPath>
</Reference>
</ItemGroup>
Depois de recarregar seu projeto no VS.NET, a caixa de diálogo Referência de Montagem ficará um pouco confusa com essas mudanças e você pode encontrar alguns avisos sobre montagens com o processador de destino errado, mas todas as suas compilações funcionarão bem.
Resolver a questão MSI é o próximo, e infelizmente isso vai exigir uma ferramenta non-VS.NET: Eu prefiro de Caphyon Installer Avançada para o efeito, uma vez que retira o truque básico envolvido (criar um MSI comum, bem como de 32 bits e MSIs específicos de 64 bits e usar um iniciador de configuração .EXE para extrair a versão correta e fazer as correções necessárias no tempo de execução) muito, muito bem.
Você provavelmente pode obter os mesmos resultados usando outras ferramentas ou o conjunto de ferramentas XML do Windows Installer (WiX) , mas o Advanced Installer torna as coisas tão fáceis (e é bastante acessível) que eu nunca realmente olhei para alternativas.
Uma coisa para a qual você ainda pode exigir o WiX, mesmo ao usar o Advanced Installer, é para suas ações personalizadas da classe .NET Installer. Embora seja trivial especificar certas ações que devem ser executadas apenas em certas plataformas (usando as condições de execução VersionNT64 e NOT VersionNT64, respectivamente), as ações personalizadas de IA integradas serão executadas usando o Framework de 32 bits, mesmo em máquinas de 64 bits .
Isso pode ser corrigido em uma versão futura, mas por agora (ou ao usar uma ferramenta diferente para criar seus MSIs que tem o mesmo problema), você pode usar o suporte de ação personalizada gerenciada do WiX 3.0 para criar DLLs de ação com a quantidade adequada de bits que será executado usando o Framework correspondente.
Editar: a partir da versão 8.1.2, o Instalador Avançado suporta corretamente ações personalizadas de 64 bits. Desde a minha resposta original, seu preço aumentou um pouco, infelizmente, embora ainda seja um valor extremamente bom quando comparado ao InstallShield e seus semelhantes ...
Editar: Se suas DLLs estiverem registradas no GAC, você também pode usar as tags de referência padrão desta forma (SQLite como exemplo):
<ItemGroup Condition="'$(Platform)' == 'x86'">
<Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
<Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64" />
</ItemGroup>
A condição também é reduzida a todos os tipos de compilação, liberação ou depuração, e apenas especifica a arquitetura do processador.