Ter como alvo tanto de 32 bits e de 64 bits com o Visual Studio na mesma solução / projeto

StackOverflow https://stackoverflow.com/questions/145803

Pergunta

Eu tenho um pequeno dilema sobre como configurar o meu visual studio constrói para multi-alvo.

Fundo: c # .NET v2.0 com p / invocar em 3rd party 32 bit DLL, SQL v3.5 compacto SP1, com um projeto de instalação. Agora, o alvo plataforma está definido para x86 para que possa ser executado no Windows x64.

O terceiro partido empresa acaba de lançar 64 versões de seu DLL de bits e eu quero construir um programa de 64 bits dedicado.

Isto levanta algumas questões que eu não tenho as respostas ainda. Quero ter exatamente a mesma base de código. Devo construir com referências a tanto o conjunto de 32 bits do DLL de 64 bits ou DLL. (Ambos 3rd party e SQL Server Compact)

Isso pode ser resolvido com 2 novos conjuntos de configurações (Debug64 e Release64)?

Devo criar 2 projetos de instalação separadas (std. Projetos visual studio, não Wix ou qualquer outro utilitário), ou isso pode ser resolvido dentro do mesmo .msi?

Todas as idéias e / ou recomendações seria bem-vinda.

Foi útil?

Solução

Sim, você pode direcionar x86 e x64 com a mesma base de código no mesmo projeto. Em geral, as coisas vão trabalhar apenas se você criar as configurações solução certa em VS.NET (embora P / Invoke para inteiramente DLLs não gerenciados provavelmente irá exigir algum código condicional): os elementos que eu encontrei para exigir atenção especial são:

  • As referências aos conjuntos fora gerenciados com o mesmo nome, mas o seu próprio número de bits específica (isso também se aplica a interoperabilidade montagens)
  • O pacote MSI (que, como já foi observado, será necessário direcionar x86 ou x64)
  • Qualquer ações personalizadas baseadas em classes .NET Installer em seu pacote MSI

A questão referência de montagem não pode ser resolvido inteiramente dentro VS.NET, uma vez que só irá permitir que você adicione uma referência com um nome dado a um projeto de uma só vez. Para contornar esse problema, edite o arquivo de projeto manualmente (em VS, clique com o botão direito seu arquivo de projeto no Solution Explorer, selecione Descarregar Projeto, em seguida, clique com botão direito novamente e selecione Edit). Depois de adicionar uma referência para, digamos, a versão x86 de uma montagem, o arquivo de projeto irá conter algo como:

<Reference Include="Filename, ..., processorArchitecture=x86">
  <HintPath>C:\path\to\x86\DLL</HintPath>
</Reference>

Enrole essa marca de referência dentro de uma tag ItemGroup indicando a configuração da solução que se aplica, por exemplo:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
   <Reference ...>....</Reference>
</ItemGroup>

Em seguida, copie e cole a tag inteira ItemGroup, e editá-lo 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 em VS.NET, o diálogo Assembléia Referência será um pouco confuso com essas mudanças, e você pode encontrar alguns avisos sobre conjuntos com o processador alvo errado, mas todo o seu constrói vai funcionar muito bem.

Resolver a questão MSI é o próximo, e, infelizmente, este serão necessitam de uma ferramenta non-VS.NET: Eu prefiro de Caphyon Avançado Installer para o efeito, uma vez que retira o truque básico envolvido (criar um MSI comum, bem como de 32 bits e 64 bits específica MSIs, e usar um lançador de configuração .EXE para extrair a versão correta e fazer os ajustes necessários em tempo de execução) muito, muito bem.

Você provavelmente pode alcançar os mesmos resultados usando outras ferramentas ou o Windows Installer XML (WiX) conjunto de ferramentas , mas avançada Installer torna as coisas fáceis (e é bastante acessível em que) que eu nunca realmente olhou para alternativas.

Uma coisa que você pode ainda exigem WiX para que, mesmo quando se utiliza avançada Installer, é por suas ações personalizadas .NET classe de instalador. Embora seja trivial para especificar determinadas ações que só deve ser executado em certas plataformas (usando as condições de execução VersionNT64 e não VersionNT64, respectivamente), o built-in personalizado ações AI serão executados usando o 32-bit Framework, mesmo em máquinas de 64 bits .

Isso pode ser corrigido em uma versão futura, mas por agora (ou quando se usa uma ferramenta diferente para criar o seu MSIs que tem o mesmo problema), você pode usar WiX 3,0 de apoio de ação personalizada gerenciada para criar DLLs de ação com o bitness adequada que será executado usando o quadro correspondente.


Edit: a partir da versão 8.1.2, Advanced Installer suporta corretamente ações personalizadas de 64 bits. Desde a minha resposta original, seu preço aumentou um pouco, infelizmente, mesmo que ele ainda é extremamente bom valor quando comparado ao InstallShield e sua laia ...


Edit: Se suas DLLs estão registrados no GAC, você também pode usar as tags de referência padrão desta forma (SQLite como um 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 é reduzido para baixo para todos os tipos de construção, lançamento ou de depuração, e apenas especifica a arquitetura do processador.

Outras dicas

Vamos dizer que você tem a compilação DLLs para ambas as plataformas, e eles estão no seguinte local:

C:\whatever\x86\whatever.dll
C:\whatever\x64\whatever.dll

Você só precisa editar o arquivo .csproj deste:

<HintPath>C:\whatever\x86\whatever.dll</HintPath>

Para isto:

<HintPath>C:\whatever\$(Platform)\whatever.dll</HintPath>

Você deve então ser capaz de construir o seu projecto visando ambas as plataformas, e MSBuild irá procurar no diretório correto para a plataforma escolhida.

Não tenho certeza da resposta total a sua pergunta - mas pensei que eu gostaria de salientar um comentário na seção Informações adicionais do SQL Compact página de download 3.5 SP1 vendo que você está olhando x64 -. Espero que ajude

Devido a alterações no SQL Server Compact SP1 ea versão adicional de 64 bits suporte, instalado centralmente e misturado ambientes de modo de versão de 32-bit SQL Server Compact 3.5 e 64 bits versão do SQL Server Compact 3.5 SP1 pode criar o que parece ser problemas intermitentes. Para minimizar o potencial para conflitos, e para permitir plataforma de implementação neutra de gerenciado aplicativos cliente, centralmente instalar a versão do SQL 64-bit Server Compact 3.5 SP1 usando o Windows Installer (MSI) também requer a instalação da versão de 32 bits do SQL Server Compact 3.5 SP1 MSI Arquivo. Para aplicações que só exigem nativa de 64 bits, privado implantação da versão de 64 bits SQL Server Compact 3.5 SP1 pode ser utilizado.

Eu li isso como "incluir os arquivos de 32 bits SQLCE bem como os arquivos de 64 bits" se distribuir para 64 bits clientes.

torna a vida interessante eu acho .. devo dizer que eu amo a linha "o que parece ser problemas intermitentes" ... soa um pouco como "você está imaginando coisas, mas apenas no caso, fazer isso ..."

Quanto à sua última pergunta. O mais provável é que você não pode resolver isso dentro de um único MSI. Se você estiver usando pastas de registro / sistema ou qualquer coisa relacionada, a própria MSI deve estar ciente disso e você deve preparar um 64bit MSI para instalar corretamente na máquina de 32 bits.

Há uma possibilidade de que você pode torná-lo produto instalado como um 32-lo aplicação e ainda ser capaz de fazê-lo funcionar como 64 bit um, mas eu acho que pode ser um pouco difícil de alcançar.

Dito isto, acho que você deve ser capaz de manter uma única base de código para tudo. Na minha atual local de trabalho, conseguimos fazê-lo. (Mas que levou alguns malabarismos para fazer tudo jogar juntos)

Espero que isso ajude. Heres um link para algumas informações relacionadas com 32/64 questões bits: http: //blog.typemock. com / 2008/07 / registro-on-windows-64-bit-double-your.html

Se você usar Ações personalizadas escritas em .NET como parte de seu instalador MSI, então você tem um outro problema.

O 'calço' que executa estas ações personalizadas é sempre de 32 bits, em seguida, sua ação personalizada irá executar 32 bits, bem como, apesar do que alvo que você especificar.

Mais informações e alguns ninja move-se para dar a volta (basicamente mudar o MSI para usar a versão deste calço 64 bit)

Construir uma MSI no Visual Studio 2005/2008 para trabalhar em um SharePoint 64

64-bit Managed ações personalizadas com Visual Studio

Você pode gerar duas soluções de forma diferente e fundi-los depois! Eu fiz isso por VS 2010. e ele funciona. Eu tinha 2 diferentes soluções geradas pelo CMake e eu fundiu-los

Você pode usar uma condição para um ItemGroup para as referências DLL no arquivo de projeto.
Isso fará com que Visual Studio para verificar novamente a condição e referências sempre que mudar a configuração ativa.
Basta adicionar uma condição para cada configuração.

Exemplo:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <Reference Include="DLLName">
      <HintPath>..\DLLName.dll</HintPath>
    </Reference>
    <ProjectReference Include="..\MyOtherProject.vcxproj">
      <Project>{AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT}</Project>
      <Name>MyOtherProject</Name>
    </ProjectReference>
  </ItemGroup>

Uma .Net construção com x86 / x64 Dependências

Enquanto todas as outras respostas lhe dar uma solução para fazer diferentes versões de acordo com a plataforma, eu dar-lhe uma opção para ter apenas a configuração "AnyCPU" e fazer uma compilação que funciona com o x86 e x64 DLLs.

Você tem que escrever algum código de canalização para isso. Eu não poderia começar este trabalho com app. Se alguém sabe uma maneira de resolvê-lo via app.config eu realmente gostaria de saber.

Resolução de x86 / x64-DLLs corretas em tempo de execução

Passos:

  1. Use AnyCPU em csproj
  2. Decida se você só faz referência a x86 ou as DLLs x64 em seus csprojs. Adaptar as configurações UnitTests para as configurações de arquitetura que você escolheu. É importante para a depuração / executar os testes dentro VisualStudio.
  3. Em referência em Propriedades set Copy Local & Specific Versão para false
  4. Se livrar das advertências arquitetura adicionando esta linha ao primeiro PropertyGroup em todos os seus arquivos csproj onde fazem referência x86 / x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. Adicione esta roteiro postbuild para o seu projeto de inicialização, usar e modificar os caminhos deste script sp que ele copia todos os seus x86 / x64 dlls em subpastas da 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ê iria começar a aplicação agora, você recebe uma exceção que o conjunto não pôde ser encontrado.

  6. Registrar o direito evento AssemblyResolve no início do seu ponto de entrada do aplicativo

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
    

    withthis método:

    /// <summary>
    /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve
    /// </summary>
    /// <param name="sender">The app domain</param>
    /// <param name="resolveEventArgs">The resolve event args</param>
    /// <returns>The architecture dependent assembly</returns>
    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ê tem testes de unidade fazer um TestClass com um método que tem uma AssemblyInitializeAttribute e também registrar o acima TryResolveArchitectureDependency-Handler lá. (Isto não será executado, por vezes, se você executar testes individuais dentro do estúdio visual, as referências serão resolvidos não a partir do bin UnitTest. Portanto a decisão na etapa 2 é importante.)

Benefícios:

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

Desvantagens: - Não há erros em tempo de compilação quando x86 / x64 dlls não coincidem. - Você ainda deve executar o teste em ambos os modos

Se preferir, crie um segundo arquivo executável que é exclusivo para a arquitetura x64 com Corflags.exe no roteiro postbuild

Outras variantes para experimentar: - Você não precisa o manipulador de eventos AssemblyResolve se assegurar de outra forma que as DLLs são copiados na pasta de binário no arranque (Avaliar a arquitetura do processo -.> Move dlls correspondente de x64 / x86 para a pasta bin e verso) - Em Installer avaliar arquitetura e excluir os binários para a arquitetura errada e mover as pessoas certas para a pasta bin

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top