c# - error - excepción de hresult 0x8007000b)''
Cómo enlazar tarde lib de 32 bits/64 bits en tiempo de ejecución (3)
Tengo un problema similar, pero sutilmente diferente de, que se describe aquí (Cargando ensamblajes y sus dependencias).
Tengo una DLL C ++ para representación 3D que es lo que vendemos a los clientes. Para los usuarios de .NET tendremos un contenedor CLR a su alrededor. La DLL de C ++ puede compilarse en versiones de 32 y 64 bits, pero creo que esto significa que necesitamos tener dos envolturas CLR ya que CLR se une a una DLL específica.
Digamos ahora que nuestro cliente tiene una aplicación .NET que puede ser de 32 o 64 bits, y que al tratarse de una aplicación .NET pura deja el CLR para resolverlo desde un único conjunto de ensamblajes. La pregunta es cómo puede el código de la aplicación elegir dinámicamente entre nuestras combinaciones CLR / DLL de 32 y 64 bits en tiempo de ejecución.
Incluso más específicamente, ¿la respuesta sugerida a la pregunta antes mencionada también se aplica aquí (es decir, crea un controlador ResolveEvent)?
Me encontré con un escenario similar hace un tiempo. Un kit de herramientas que estaba usando no se comportó bien en un entorno de 64 bits y no pude encontrar una forma de obligar dinámicamente a los ensamblajes a vincularse como de 32 bits.
Es posible obligar a sus ensamblajes a trabajar en modo de 32 bits, pero esto requiere parchear el encabezado CLR, (hay una herramienta que lo hace en el Marco) y si sus ensamblajes tienen un nombre fuerte, esto no funciona.
Me temo que tendrá que crear y publicar dos conjuntos de binarios para plataformas de 32 y 64 bits.
Pude hacer esto hace aproximadamente un año, pero ya no recuerdo todos los detalles. Básicamente, puede usar IntPtr.Size para determinar qué DLL cargar y luego realizar la LoadLibrary actual a través de p / Invoke. En ese punto, tienes el módulo en la memoria y deberías poder simplemente p / invocar funciones desde adentro; el mismo nombre del módulo no debería volver a cargarse.
Creo, sin embargo, que en mi aplicación en realidad tenía el DLL de C ++ registrarse como un servidor COM y luego accedí a su funcionalidad a través de un contenedor .NET generado, así que no sé si alguna vez probé p / Invocar directamente.
Finalmente tengo una respuesta para esto que parece funcionar.
Compila las versiones de 32 y 64 bits, administradas y no administradas, en carpetas separadas. Luego, haga que la aplicación .NET elija en tiempo de ejecución de qué directorio cargar los ensamblados.
El problema con el uso del ResolveEvent es que solo recibe una llamada si no se encuentran los ensamblados, por lo que es fácil terminar accidentalmente con las versiones de 32 bits. En su lugar, use un segundo objeto AppDomain donde podamos cambiar la propiedad ApplicationBase para que apunte a la carpeta correcta. Entonces terminas con un código como:
static void Main(String[] argv)
{
// Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit
// sub-directories.
AppDomainSetup objADS = new AppDomainSetup();
System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
switch (System.IntPtr.Size)
{
case (4): assemblyDir += "//win32//";
break;
case (8): assemblyDir += "//x64//";
break;
}
objADS.ApplicationBase = assemblyDir;
// We set the PrivateBinPath to the application directory, so that we can still
// load the platform neutral assemblies from the app directory.
objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
AppDomain objAD = AppDomain.CreateDomain("", null, objADS);
if (argv.Length > 0)
objAD.ExecuteAssembly(argv[0]);
else
objAD.ExecuteAssembly("MyApplication.exe");
AppDomain.Unload(objAD);
}
Usted termina con 2 exes: su aplicación normal y una segunda aplicación de cambio que elige qué bits cargar. Nota: no me puedo atribuir el mérito por los detalles de esto. Uno de mis colegas sospechó eso dado mi puntero inicial. Si se registra en , le asignaré la respuesta