Pregunta

Tengo un pequeño dilema sobre cómo configurar mis compilaciones de estudio visual para la orientación múltiple.

Antecedentes: c # .NET v2.0 con p / invocación en DLL de 32 bits de terceros, SQL compact v3.5 SP1, con un proyecto de instalación. En este momento, el objetivo de la plataforma está configurado en x86 para que pueda ejecutarse en Windows x64.

La compañía de terceros acaba de lanzar versiones de 64 bits de sus DLL y quiero crear un programa dedicado de 64 bits.

Esto plantea algunas preguntas para las que aún no tengo las respuestas. Quiero tener exactamente la misma base de código. Debo compilar con referencias al conjunto de 32 bits de DLL o 64 bits de DLL. (Tanto de terceros como de SQL Server Compact)

¿Se puede resolver esto con 2 nuevos conjuntos de configuraciones (Debug64 y Release64)?

¿Debo crear 2 proyectos de configuración separados (proyectos de estudio visual estándar, sin Wix ni ninguna otra utilidad), o puede resolverse dentro del mismo .msi?

Cualquier idea y / o recomendación sería bienvenida.

¿Fue útil?

Solución

Sí, puede apuntar a x86 y x64 con la misma base de código en el mismo proyecto. En general, las cosas simplemente funcionarán si crea las configuraciones de solución correctas en VS.NET (aunque P / Invocar a DLL completamente no administrados probablemente requerirá algún código condicional): los elementos que encontré que requieren atención especial son:

  • Referencias a ensamblados administrados externos con el mismo nombre pero con su propio bitness específico (esto también se aplica a ensamblados de interoperabilidad COM)
  • El paquete MSI (que, como ya se ha señalado, deberá apuntar a x86 o x64)
  • Cualquier acción personalizada .NET Installer Class-based en su paquete MSI

El problema de referencia de ensamblado no se puede resolver por completo dentro de VS.NET, ya que solo le permitirá agregar una referencia con un nombre dado a un proyecto una vez. Para solucionar este problema, edite el archivo del proyecto manualmente (en VS, haga clic con el botón derecho en el archivo del proyecto en el Explorador de soluciones, seleccione Descargar proyecto, luego haga clic con el botón derecho nuevamente y seleccione Editar) Después de agregar una referencia a, digamos, la versión x86 de un ensamblaje, su archivo de proyecto contendrá algo como:

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

Envuelva esa etiqueta de referencia dentro de una etiqueta ItemGroup que indica la configuración de la solución a la que se aplica, por ejemplo:

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

Luego, copie y pegue la etiqueta completa de ItemGroup y edítela para que contenga los detalles de su DLL de 64 bits, por ejemplo:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
  <Reference Include="Filename, ..., processorArchitecture=AMD64">
     <HintPath>C:\path\to\x64\DLL</HintPath>
   </Reference>
</ItemGroup>

Después de volver a cargar su proyecto en VS.NET, el cuadro de diálogo Referencia de ensamblaje se verá un poco confundido por estos cambios, y puede encontrar algunas advertencias sobre ensamblajes con el procesador de destino incorrecto, pero todas sus compilaciones funcionarán bien.

La resolución del problema de MSI es lo siguiente, y desafortunadamente esto requerirá una herramienta que no sea VS.NET: prefiero Caphyon's Instalador avanzado para ese propósito, ya que realiza el truco básico involucrado (cree un MSI común, así como MSI específicos de 32 y 64 bits, y use un iniciador de configuración .EXE para extraer la versión correcta y hacer las reparaciones necesarias en tiempo de ejecución) muy, muy bien.

Probablemente pueda lograr los mismos resultados utilizando otras herramientas o el conjunto de herramientas XML (WiX) de Windows Installer , pero El instalador avanzado hace las cosas tan fáciles (y es bastante asequible) que nunca he visto alternativas.

Sin embargo, una cosa para la que puede todavía requiere WiX, incluso cuando usa el instalador avanzado, es para sus acciones personalizadas de clase de instalador .NET. Aunque es trivial especificar ciertas acciones que solo deberían ejecutarse en ciertas plataformas (usando las condiciones de ejecución de VersionNT64 y NOT VersionNT64, respectivamente), las acciones personalizadas de AI integradas se ejecutarán usando el Framework de 32 bits, incluso en máquinas de 64 bits .

Esto puede corregirse en una versión futura, pero por ahora (o cuando use una herramienta diferente para crear sus MSI que tengan el mismo problema), puede usar el soporte de acción personalizada administrada de WiX 3.0 para crear DLL de acción con el Bitness adecuado que se ejecutará utilizando el marco correspondiente.


Editar: a partir de la versión 8.1.2, el instalador avanzado admite correctamente acciones personalizadas de 64 bits. Desde mi respuesta original, su precio ha aumentado bastante, desafortunadamente, a pesar de que sigue siendo un valor extremadamente bueno en comparación con InstallShield y su tipo ...


Editar: si sus archivos DLL están registrados en el GAC, también puede usar las etiquetas de referencia estándar de esta manera (SQLite como ejemplo):

<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>

La condición también se reduce a todos los tipos de compilación, versión o depuración, y solo especifica la arquitectura del procesador.

Otros consejos

Digamos que tiene las compilaciones de DLL para ambas plataformas, y están en la siguiente ubicación:

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

Simplemente necesita editar su archivo .csproj de esto:

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

A esto:

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

Debería poder construir su proyecto dirigido a ambas plataformas, y MSBuild buscará en el directorio correcto para la plataforma elegida.

No estoy seguro de la respuesta total a su pregunta, pero pensé en señalar un comentario en la sección Información adicional de página de descarga de SQL Compact 3.5 SP1 al ver que está viendo x64, espero que ayude.

  

Debido a cambios en SQL Server Compact   SP1 y versión adicional de 64 bits   soporte, centralmente instalado y mixto   entornos de modo de la versión de 32 bits de   SQL Server Compact 3.5 y 64 bits   versión de SQL Server Compact 3.5 SP1   puede crear lo que parece ser   problemas intermitentes Para minimizar el   potencial para conflictos y para habilitar   despliegue neutral de la plataforma de administrado   aplicaciones cliente, centralmente   Instalar la versión de 64 bits de SQL   Server Compact 3.5 SP1 utilizando el   El archivo de Windows Installer (MSI) también   requiere instalar la versión de 32 bits   de MSI de SQL Server Compact 3.5 SP1   expediente. Para aplicaciones que solo   requieren nativo de 64 bits, privado   implementación de la versión de 64 bits de   SQL Server Compact 3.5 SP1 puede ser   utilizado.

Leí esto como " incluye los archivos SQLCE de 32 bits así como los archivos de 64bit " si se distribuye para clientes de 64 bits.

Hace la vida interesante, supongo ... debo decir que me encanta el & "; lo que parecen ser problemas intermitentes &"; línea ... suena un poco como & "; estás imaginando cosas, pero por si acaso, haz esto ... &";

Con respecto a su última pregunta. Lo más probable es que no pueda resolver esto dentro de un solo MSI. Si está utilizando carpetas de registro / sistema o cualquier cosa relacionada, el MSI debe ser consciente de esto y debe preparar un MSI de 64 bits para instalarlo correctamente en la máquina de 32 bits.

Existe la posibilidad de que pueda instalar su producto como una aplicación 32 it y aún así poder ejecutarlo como 64 bit one, pero creo que puede ser algo difícil de lograr.

Dicho esto, creo que deberías poder mantener una sola base de código para todo. En mi lugar de trabajo actual lo hemos logrado. (pero tomó un poco de malabarismo para que todo jugara juntos)

Espero que esto ayude. Aquí hay un enlace a información relacionada con problemas de 32/64 bits: http: //blog.typemock. com / 2008/07 / Registry-on-windows-64-bit-double-your.html

Si usa acciones personalizadas escritas en .NET como parte de su instalador MSI, entonces tiene otro problema.

El 'shim' que ejecuta estas acciones personalizadas siempre es de 32 bits, entonces su acción personalizada también se ejecutará a 32 bits, a pesar del objetivo que especifique.

Más información & amp; algunos movimientos ninja para moverse (básicamente cambiar el MSI para usar la versión de 64 bits de esta cuña)

Creación de un MSI en Visual Studio 2005/2008 para trabajar en un SharePoint 64

Acciones personalizadas administradas de 64 bits con Visual Studio

¡Puede generar dos soluciones de manera diferente y fusionarlas después! Hice esto para VS 2010. y funciona. Tenía 2 soluciones diferentes generadas por CMake y las fusioné

Puede usar una condición para un Grupo de elementos para las referencias dll en el archivo del proyecto.
Esto hará que Visual Studio vuelva a verificar la condición y las referencias cada vez que cambie la configuración activa.
Simplemente agregue una condición para cada configuración.

Ejemplo:

 <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>

Una compilación .Net con dependencias x86 / x64

Si bien todas las demás respuestas le dan una solución para hacer diferentes Builds de acuerdo con la plataforma, le doy la opción de tener solo " AnyCPU " configuración y hacer una compilación que funcione con sus dlls x86 y x64.

Debe escribir un código de plomería para esto. No pude hacer que esto funcionara con app.config. Si alguien más conoce una forma de resolverlo a través de app.config, realmente me gustaría saberlo.

Resolución de x86 / x64-dlls correctas en tiempo de ejecución

Pasos:

  1. Use AnyCPU en csproj
  2. Decide si solo haces referencia a los dlls x86 o x64 en tus csprojs. Adapte la configuración de UnitTests a la configuración de arquitectura que haya elegido. Es importante para depurar / ejecutar las pruebas dentro de VisualStudio.
  3. En Propiedades de referencia, establezca Copiar local & amp; Versión específica a false
  4. Deshágase de las advertencias de arquitectura agregando esta línea al primer PropertyGroup en todos sus archivos csproj donde haga referencia a x86 / x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. Agregue este script postbuild a su proyecto de inicio, use y modifique las rutas de este script sp que copia todas sus dlls x86 / x64 en las subcarpetas correspondientes de su bin de construcción \ 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

    - > Cuando comenzaría la aplicación ahora, obtendrá una excepción que no se pudo encontrar el ensamblado.

  6. Registre el evento AssemblyResolve justo al comienzo del punto de entrada de su aplicación

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
    

    con este 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. Si tiene pruebas unitarias, haga una clase de prueba con un método que tenga un atributo AssemblyInitializeAttribute y también registre el TryResolveArchitectureDependency-Handler anterior allí. (Esto no se ejecutará a veces si ejecuta pruebas individuales dentro de Visual Studio, las referencias se resolverán no desde el bin UnitTest. Por lo tanto, la decisión en el paso 2 es importante).

Beneficios:

  • Una instalación / compilación para ambas plataformas

inconvenientes:  - No hay errores en el momento de la compilación cuando x86 / x64 dlls no coinciden.  - ¡Aún deberías ejecutar la prueba en ambos modos!

Opcionalmente, cree un segundo ejecutable que sea exclusivo para la arquitectura x64 con Corflags.exe en el script postbuild

Otras variantes para probar:  - No necesitaría el controlador de eventos AssemblyResolve si se asegura de lo contrario que los dlls se copien en su carpeta binaria al inicio (Evalúe la arquitectura del proceso - & Gt; mueva los dlls correspondientes de x64 / x86 a la carpeta bin y viceversa).  - En el instalador, evalúe la arquitectura y elimine los archivos binarios para la arquitectura incorrecta y mueva los correctos a la carpeta bin.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top