Usar de forma condicional la referencia de 32/64 bits cuando se construye en Visual Studio

Tengo un proyecto que se construye en 32/64 bits y tiene dependencias correspondientes de 32/64 bits. Quiero poder cambiar las configuraciones y utilizar la referencia correcta, pero no sé cómo decirle a Visual Studio que use la dependencia apropiada para la architecture.

Tal vez estoy haciendo esto de la manera incorrecta, pero quiero poder cambiar entre x86 y x64 en el menú desplegable de configuración y hacer que la DLL a la que se hace referencia sea la correcta.

Esto es lo que hice en un proyecto anterior, que requerirá la edición manual de los archivos .csproj. También necesita directorios separados para los diferentes binarios, idealmente hermanos entre sí, y con el mismo nombre que la plataforma a la que se dirige.

Después de agregar las referencias de una sola plataforma al proyecto, abra .csproj en un editor de texto. Antes del primer elemento dentro del elemento , agregue el siguiente código, que ayudará a determinar en qué plataforma está ejecutando (y comstackndo).

   x86 AMD64  

Luego, para las referencias específicas de su plataforma, realiza cambios como los siguientes:

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

Tenga en cuenta el uso de la propiedad $(CurrentPlatform) , que definimos anteriormente. En cambio, podría usar condicionales para qué ensamblajes incluir qué plataforma. También podría necesitar:

  • Reemplace $(PROCESSOR_ARCHITEW6432) y $(PROCESSOR_ARCHITECTURE) con $(Platform) para considerar SOLAMENTE la plataforma de destino de los proyectos
  • Modifique la lógica de determinación de plataforma para que sea apropiada para la máquina actual, de modo que no esté creando / haciendo referencia a un binario de 64 bits para ejecutar en una plataforma de 32 bits.

Lo escribí originalmente para una Wiki interna en el trabajo, sin embargo, lo he modificado y publicado todo el proceso en mi blog , si está interesado en las instrucciones detalladas paso a paso.

AFAIK, si su proyecto requiere referencias que son específicas de 32 bits o de 64 bits (es decir, ensamblados de interoperabilidad COM), y no tiene interés en editar manualmente el archivo .csproj, entonces tendrá que crear archivos de 32 bits por separado y Proyectos de 64 bits.

Debo señalar que la siguiente solución no ha sido probada, pero debería funcionar. Si está dispuesto a editar manualmente el archivo .csproj, entonces debería poder lograr el resultado deseado con un único proyecto. El archivo .csproj es solo un script de MSBuild, así que para una referencia completa, mira aquí . Una vez que haya abierto el archivo .csproj en un editor, ubique los elementos . Debería poder dividir estos elementos en 3 grupos de elementos distintos: referencias que no son específicas de la plataforma, referencias específicas de x86 y referencias específicas de x64.

Aquí hay un ejemplo que asume que su proyecto está configurado con plataformas de destino llamadas “x86” y “x64”

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

Ahora, cuando configura su proyecto / configuración de comstackción de la solución para apuntar a la plataforma x86 o x64, debe incluir las referencias adecuadas en cada caso. Por supuesto, tendrá que jugar con los elementos . Incluso podría configurar proyectos ficticios donde agregue las referencias x86 y x64, y luego simplemente copie los elementos necesarios de esos archivos ficticios de proyecto a su archivo de proyecto “real”.

Editar 1
Aquí hay un enlace a los elementos comunes del proyecto MSBuild, que dejé accidentalmente en la publicación original: http://msdn.microsoft.com/en-us/library/bb629388.aspx

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   

Estoy haciendo referencia a las DLL x86, ubicadas en, por ejemplo, \ component \ v3_NET4, en mi proyecto. Las DLL específicas para x86 / x64 se encuentran en subcarpetas denominadas “x86” y “x64” respectivamente.

Luego estoy usando una secuencia de comandos previa a la comstackción que copia las DLL apropiadas (x86 / x64) en la carpeta referenciada, en base a $ (PlatformName).

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

Funciona para mi.

Enfrenté el mismo problema y pasé bastante tiempo buscando una solución decente. La mayoría de las personas ofrece la edición manual de los archivos de solución de Visual Studio, lo que es bastante tedioso, propenso a errores y confuso cuando se exploran estos archivos editados en la GUI de Visual Studio posteriormente. Cuando ya me rendí, la solución surgió por sí misma. Es muy similar a lo que recomienda Micke en su respuesta anterior.

En el administrador de cuentas creé dos objectives de comstackción separados para las plataformas x86 y x64, como de costumbre. Luego, agregué una referencia al ensamblaje x86 a mi proyecto. En este punto, creí que el proyecto está configurado para la construcción x86 solamente y nunca se comstackrá para la configuración x64, a menos que haga una edición manual de la misma tal como lo sugirió Hugo arriba.

Después de un tiempo, finalmente me olvidé de la limitación y accidentalmente comencé la comstackción x64. Por supuesto, la comstackción falló. Pero importante fue el mensaje de error que recibí. El mensaje de error indicó que el ensamblado nombrado exactamente como mi ensamblado x86 referenciado falta en la carpeta destinada como objective de comstackción x64 para mi solución.

Habiendo notado esto, he copiado manualmente el ensamblaje x64 apropiado en este directorio. ¡Gloria! Mi construcción x64 tuvo éxito milagrosamente con el ensamblaje adecuado encontrado y vinculado implícitamente. Fue cuestión de minutos modificar mi solución para establecer un directorio de destino de comstackción para el ensamblaje x64 en esta carpeta. Después de estos pasos, la solución se genera automáticamente para x86 y x64 sin ninguna edición manual de los archivos de MSBuild.

Para resumir:

  1. Crear objectives x86 y x64 en un solo proyecto
  2. Agregue todas las referencias de proyecto adecuadas a los ensamblajes x86
  3. Establezca un directorio de destino de comstackción común para todos los ensamblados x64
  4. En caso de que tenga ensamblados x64 listos, simplemente cópielos una vez en su directorio de destino de comstackción x64.

Después de completar estos pasos, su solución se comstackrá correctamente para las configuraciones x86 y x64.

Esto funcionó para mí en el proyecto Visual Studio 2010 .NET 4.0 C #. Evidentemente, este es un tipo de comportamiento interno no documentado de Visual Studio, que podría estar sujeto a cambios en las versiones de 2012, 2013 y 2015. Si alguien intenta probar otras versiones, por favor comparta su experiencia.

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.