how - Carga de DLL de 32 o 64 bits desde el código administrado.Net
how to use fuslogvw (5)
Lo mejor que he encontrado es lo siguiente:
- Distribuir mi aplicación con dos DLL llamados 64 o 32
- En el código de inicio principal incluye lo siguiente:
File.Delete(Application.StartupPath + @"/scilexer.dll"); { // Check for 64 bit and copy the proper scilexer dll if (IntPtr.Size == 4) { File.Copy(Application.StartupPath + @"/scilexer32.dll", Application.StartupPath + @"/scilexer.dll"); } else { File.Copy(Application.StartupPath + @"/scilexer64.dll", Application.StartupPath + @"/scilexer.dll"); } }
Tengo una DLL no administrada (scilexer.dll del editor de código Scintilla, utilizada por Scintilla.Net de CodePlex ) que se carga desde una aplicación administrada a través del componente Scintilla.Net. La aplicación administrada por Windows se ejecuta sin problemas en entornos de 32 y 64 bits, pero necesito crear instalaciones diferentes que utilicen 64 o 32 scilexer.dll.
¿Hay alguna forma de distribuir ambas DLL en formato de 32 y 64 bits para que el cargador DLL de .Net Framework cargue la DLL no administrada en el formato de 32 o 64 bits dependiendo de alguna opción .config o de algunas "cosas mágicas de nombre de ruta"?
Los dlls no administrados se pueden instalar en el GAC lado a lado con sus contrapartes gestionados. Este artículo debería explicar cómo funciona.
Puedes poner el dll en system32. Los 32 bits en syswow64 y los 64 bits en el sistema real32. Para la aplicación de 32 bits, cuando tienen acceso al sistema 32, se les redirige a Syswow64.
Puede crear una entrada en el registro. La clave del software tiene una subclave llamada Wow6432Node que la aplicación de 32 bits ve como la clave del software.
Esto es lo que hace el instalador de PowerShell .
Lamentablemente, no sé nada sobre esta DLL en particular. Sin embargo, al hacer la P / invocación usted mismo, y puede hacer frente a una pequeña duplicación, es posible crear un proxy para cada plataforma.
Por ejemplo, supongamos que tiene la siguiente interfaz, que debería implementarse mediante una DLL de 32 o 64 bits:
public interface ICodec {
int Decode(IntPtr input, IntPtr output, long inputLength);
}
Usted crea los proxies:
public class CodecX86 : ICodec {
private const string dllFileName = @"Codec.x86.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
y
public class CodecX64 : ICodec {
private const string dllFileName = @"Codec.x64.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
Y finalmente crea una fábrica que elija la adecuada para ti:
public class CodecFactory {
ICodec instance = null;
public ICodec GetCodec() {
if (instance == null) {
if (IntPtr.Size == 4) {
instance = new CodecX86();
} else if (IntPtr.Size == 8) {
instance = new CodecX64();
} else {
throw new NotSupportedException("Unknown platform");
}
}
return instance;
}
}
Como los archivos DLL se cargan de forma lenta la primera vez que se invocan, esto realmente funciona, a pesar de que cada plataforma solo puede cargar la versión que es nativa. Vea este artículo para una explicación más detallada.
P / Invoke usa LoadLibrary para cargar archivos DLL, y si ya hay una biblioteca cargada con un nombre dado, LoadLibrary lo devolverá. Entonces, si puede asignar el mismo nombre a las dos versiones del archivo DLL, puede hacer algo como esto solo una vez antes de la primera llamada a una función desde scilexer.dll, sin necesidad de duplicar las declaraciones externas:
string platform = IntPtr.Size == 4 ? "x86" : "x64";
string dll = installDir + @"/lib-" + platform + @"/scilexer.dll";
if (LoadLibrary(dll) == IntPtr.Zero)
throw new IOException("Unable to load " + dll + ".");