2010-09-24 13 views
12

Tengo dos versiones de System.Data.SQLite.DLL - para plataformas x86 y x64. La versión x86 se mantiene en la carpeta de la aplicación y la versión x64 se mantiene en la carpeta appFolder \ x64. La aplicación compilada como AnyCPU. ¿Cómo puedo cargar la versión necesaria de SQLite según la plataforma de Windows?Cargando ensamble x86 o x64

Respuesta

17

Si está usando SQLite desde http://system.data.sqlite.org, el System.Data.SQLite.DLL está completamente administrado. Existe una DLL nativa subyacente, SQLite.Interop.DLL, que debe cambiar según el proceso (32 o 64 bits).

Implemento las bibliotecas nativas en ". \ Native \ X64" para 64 bits y ". \ Native \ X86" para 32 bits. En el tiempo de ejecución P/Invoque SetDllDirectory para configurar el directorio de carga DLL apuntando a la ruta correcta para el proceso. http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx

(Nótese que no estoy familiarizado con la arquitectura de la versión del legado System.Data.SQLite.DLL de http://sqlite.phxsoftware.com)

private static class NativeMethods 
{ 
    [DllImport("kernel32.dll", CallingConvention = CallingConvention.Cdecl)] 
    internal static extern bool SetDllDirectory(string pathName); 
} 

... 

    // Underlying SQLite libraries are native. 
    // Manually set the DLL load path depending on the process. 
    var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Native"); 
    if(IntPtr.Size == 8) // or: if(Environment.Is64BitProcess) // .NET 4.0 
    { 
     path = Path.Combine(path, "X64"); 
    } 
    else 
    { 
     // X32 
     path = Path.Combine(path, "X86"); 
    } 
    NativeMethods.SetDllDirectory(path); 
+3

He resuelto este problema. Gracias. Usé "IntPtr.Size == 8". Usé AppDomain.CurrentDomain.AssemblyResolve en lugar de SetDllDirectory. – Rover

1

Puede usar Environment.Is64BitProcess para identificar el proceso como de 64 bits. (Intentaría evitar detectar excepciones como control de flujo siempre que sea posible.)

+0

Es una buena propuesta, pero no resuelve mi problema. – Rover

+0

@Rover: ¿Cómo es eso? ¿Definitivamente tienes instalado .NET de 64 bits? –

+0

Uso .NET 3.5 que no tiene esta variable. Creo que puedo verificar la versión de la plataforma, pero solo se evitan algunas excepciones, pero el ensamblaje necesario no está cargado. – Rover

0

¿No podría simplemente usar el origen de SQLite como un proyecto separado en su solución en lugar de un ensamblado precompilado? Con AnyCPU, el sistema se encargará de todo y no tiene que hacerlo en código ...

+0

Es uno de los dlls que uso dividido en x86 y x64. No tengo el código fuente de todos los dlls usados. – Rover

+0

Esto no resolverá ningún problema, ya que la arquitectura de la máquina de desarrollo no es siempre la misma que la máquina de despliegue. Cualquier CPU solo funciona para ensamblados .NET, no para archivos DLL nativos (uso de bruja SQLite bajo el capó) – BigBoss

3

Me sorprende que esto funcione en absoluto. Primero debería encontrar la versión x86 y fallar. Un enlace ensamblado fallido no produce otro intento a través de AssemblyResolve.

Claramente, el CLR no puede encontrar la versión x86 o fallará en el modo x64 también. En otras palabras, cuando arregle el problema, romperá el código de 64 bits. Primero busque el problema x86, use Fuslogvw.exe para ver qué carpetas se están sondeando para el ensamblaje.

Una solución real debería incluir mover el ensamblaje x86 a una carpeta diferente y ajustar el controlador de eventos en consecuencia. Puede probar IntPtr.Size para averiguar si se está ejecutando en modo de 64 bits (Tamaño == 8). También asegúrese de generar un nombre de ruta completo, utilizando la ruta relativa como lo hace ahora puede causar un error cuando el directorio de trabajo de la aplicación no está configurado donde usted espera que sea. Assembly.GetEntryAssembly(). Location te muestra la ruta del EXE.

+0

Eliminé el código para evitar confusiones y solo dejo una pregunta. – Rover

+0

Hmm, no creo que eso cambie mi respuesta. El último párrafo te dice cómo hacerlo bien. –

+0

Ok, revisé la plataforma, encontré el ensamblaje necesario. ¿Qué debo hacer para cargar el ensamblaje en AppDomain? – Rover

0
  1. instalación DLL apropiada en el GAC (por ejemplo, versión de 64 bits en una plataforma de 64 bits)
  2. utilice el encuadernado ensamblado en su configuración web/aplicación (posiblemente en configuración de máquina)
  3. Califique completamente cualquier referencia de ensamblaje parcial en la configuración de su web/aplicación.
5

Hay soporte incorporado para esto en 1.0.80.0 y posterior.

Si las máquinas de desarrollo y de cliente pueden tener arquitecturas de procesador diferentes, es posible que se requiera más de un paquete binario. Para esta situación, se recomienda usar la característica de precarga de la biblioteca nativa. Está disponible desde la versión 1.0.80.0 y está habilitado de forma predeterminada.(from download page)

Sin embargo, para conseguir que funcione en mi propio plug-in también tuve que añadir este antes de hacer referencia SQLite por primera vez:

// Make SQLite work... (loading dll from e.g. x64/SQLite.Interop.dll) 
System.Environment.SetEnvironmentVariable("PreLoadSQLite_BaseDirectory", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)); 

Sql.Data.SQLite... 

Ver esta pregunta: New SQLite mixed assemblies

11

Algunos prog antivir previenen que SetDllDirectory() me haya llevado mucho tiempo darme cuenta de eso. Estamos utilizando

System.Reflection.Assembly myass = System.Reflection.Assembly.GetExecutingAssembly(); 
FileInfo fi = new FileInfo(myass.Location); 
System.IntPtr moduleHandle = LoadLibraryEx(fi.Directory.FullName + "\\x64\\SQLite.Interop.DLL", IntPtr.Zero, 0); 

para cargar la DLL de 64 bits con la ruta explícita. Se carga en ese punto y .NET Runtime utilizará la DLL en memoria en lugar de buscarla en el disco.

+5

Upvote para 'myass' :) –

+0

No funcionó en mi caso. Aunque he verificado con el depurador, la biblioteca nativa se carga correctamente. SQLite todavía arroja una excepción sobre la falta de DLL nativo. – BartoszKP

Cuestiones relacionadas