Apuntando tanto a 32 bits como a 64 bits con Visual Studio en la misma solución / proyecto

Tengo un pequeño dilema sobre cómo configurar mis comstackciones de Visual Studio para multi-targeting.

Antecedentes: c # .NET v2.0 con p / invocación a DLL de 32 bits de terceros, SQL compacto v3.5 SP1, con un proyecto de instalación. En este momento, el objective de la plataforma está establecido en x86, por lo que se puede ejecutar en Windows x64.

La empresa de terceros acaba de lanzar versiones de 64 bits de sus DLL y quiero construir un progtwig dedicado de 64 bits.

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

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

¿Debo crear 2 proyectos de instalación separados (proyectos de estudio visual estándar, sin Wix o cualquier otra utilidad), o se puede resolver esto dentro del mismo .msi?

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

Sí, puede segmentar tanto x86 como x64 con la misma base de código en el mismo proyecto. En general, las cosas solo funcionarán si crea las configuraciones de solución correctas en VS.NET (aunque P / Invoke a DLL totalmente no administradas probablemente requerirá algún código condicional): los elementos que considero que requieren atención especial son:

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

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

 C:\path\to\x86\DLL  

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

  ....  

A continuación, copie y pegue toda la etiqueta ItemGroup y edítelo para que contenga los detalles de su DLL de 64 bits, por ejemplo:

   C:\path\to\x64\DLL   

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

Resolver el problema de MSI es el siguiente, y desafortunadamente esto requerirá una herramienta que no sea de VS.NET: prefiero el instalador avanzado de Caphyon para ese propósito, ya que saca el truco básico involucrado (crear un MSI común, así como de 32 bits y MSIs específicos de 64 bits, y usan un iniciador de instalación .EXE para extraer la versión correcta y realizar las correcciones necesarias en el tiempo de ejecución) muy, muy bien.

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

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

Esto puede solucionarse en una versión futura, pero por ahora (o cuando usa una herramienta diferente para crear sus MSI que tienen el mismo problema), puede usar el soporte de acciones personalizadas administradas de WiX 3.0 para crear archivos DLL de acción con el bitness apropiado que se ejecutará utilizando el Marco correspondiente.


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


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

       

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

Supongamos que tiene la comstackción 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 desde esto:

 C:\whatever\x86\whatever.dll 

A esto:

 C:\whatever\$(Platform)\whatever.dll 

Debería poder construir su proyecto orientado 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é que señalaría un comentario en la sección Información adicional de la página de descarga de SQL Compact 3.5 SP1 viendo que está viendo x64. Espero que ayude.

Debido a cambios en SQL Server Compact SP1 y soporte adicional de versiones de 64 bits, los entornos de modo mixto y centralmente instalados de la versión de 32 bits de SQL Server Compact 3.5 y la versión de 64 bits de SQL Server Compact 3.5 SP1 pueden crear lo que parece ser intermitente problemas. Para minimizar el potencial de conflictos y habilitar la implementación neutral de plataforma de las aplicaciones cliente administradas, la instalación centralizada de la versión de 64 bits de SQL Server Compact 3.5 SP1 utilizando el archivo Windows Installer (MSI) también requiere la instalación de la versión de 32 bits de SQL Server. Compact 3.5 SP1 archivo MSI. Para aplicaciones que solo requieren 64 bits nativos, se puede utilizar la implementación privada de la versión de 64 bits de SQL Server Compact 3.5 SP1.

Leí esto como “incluir los archivos SQLCE de 32 bits , así como los archivos de 64 bits” si se distribuye para clientes de 64 bits.

Hace que la vida sea interesante, supongo … debo decir que amo la línea “lo que parece ser un problema intermitente” … suena un poco como “estás imaginando cosas, pero por las dudas, haz esto …”

En cuanto a tu última pregunta. Lo más probable es que no puedas resolver esto dentro de un solo MSI. Si está utilizando carpetas de registro / sistema o cualquier cosa relacionada, la propia MSI debe ser consciente de esto y debe preparar una MSI de 64 bits para instalarla correctamente en la máquina de 32 bits.

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

Dicho esto, creo que deberías poder mantener una única base de código para todo. En mi lugar de trabajo actual lo hemos logrado. (pero tomó algunos malabares hacer que todo juegue en conjunto)

Espero que esto ayude. Aquí hay un enlace a alguna 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 de MSI, entonces tiene otro problema.

El ‘shim’ que ejecuta estas acciones personalizadas siempre es de 32 bits, luego tu acción personalizada también se ejecutará a 32 bits, a pesar de qué objective especifiques.

Más información y algunos movimientos ninja para moverse (básicamente, cambia el MSI para usar la versión de 64 bits de este shim)

Crear 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 ItemGroup para las referencias dll en el archivo de proyecto.
Esto hará que visual studio vuelva a verificar la condición y las referencias siempre que cambie la configuración activa.
Solo agrega una condición para cada configuración.

Ejemplo:

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

Una .Net comstackción con Dependencias x86 / x64

Mientras que todas las otras respuestas te dan una solución para hacer diferentes comstackciones de acuerdo con la plataforma, te doy la opción de tener solo la configuración “AnyCPU” y hacer una comstackción que funcione con tus x86 y x64 dlls.

Tienes que 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 correctos 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 UnitTests a la configuración de architecture que haya elegido. Es importante para la depuración / ejecución de las pruebas dentro de VisualStudio.
  3. En Referencia-Propiedades establecidas Copiar versión local y específica a falso
  4. Deshágase de las advertencias de architecture agregando esta línea al primer PropertyGroup en todos sus archivos csproj donde hace referencia a x86 / x64: None
  5. Agregue este script postbuild a su proyecto de inicio, utilice y modifique las rutas de acceso de este script sp que copia todos sus dlls x86 / x64 en las subcarpetas correspondientes de su bin de comstackció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 inicies la aplicación ahora, obtienes una excepción de 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:

     ///  /// 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. Si tiene pruebas unitarias, haga un TestClass con un Método que tenga un AssemblyInitializeAttribute y también registre allí el TryResolveArchitectureDependency-Handler anterior. (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 / construcción para ambas plataformas

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

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

Otras variantes para probar: – No necesitarías el manejador de eventos AssemblyResolve si aseguras que los dlls se copian en tu carpeta binaria al inicio (Evalúa la architecture del proceso -> mueve los dlls correspondientes desde x64 / x86 a la carpeta bin y viceversa). – En Installer evalúa la architecture y elimina los binarios para la architecture incorrecta y mueve los correctos a la carpeta bin.