2013-08-10 10 views
10

Sto sviluppando un programma in VB.net e utilizzando System.Data.SQLite binari precompilati per .NET, tuttavia non funziona per architetture x64 e sto riscontrando il classico problema di cultura e il caricamento non corretto file.SQLite dll per architetture x86/x64

System.BadImageFormatException: 
Could not load file or assembly 'System.Data.SQLite, Version=1.0.65.0, Culture=neutral, 
PublicKeyToken=db937bc2d44ff139' or one of its dependencies. An attempt was made to load a program with an incorrect format. 
File name: 'System.Data.SQLite, 
Version=1.0.65.0, 
Culture=neutral, 
PublicKeyToken=db937bc2d44ff139' 

C'è un modo per utilizzare un solo dll, forse:

  1. aggiungere alcune direttive come #IFDEF (x86 includono una parte di codice) o il codice x64 altro
  2. Registrati DLL per fare solo uno.
  3. Riferimento questa dll in VB.net

pensi sia altra idea migliore, come vorrei fare solo una compilation, non uno per x32 e x64 per altri.

Ad esempio (32 bit):

Private Shared Sub OpenConection(ByRef Conn As SQLite.SQLiteConnection) 
    Conn = New SQLite.SQLiteConnection("Data Source=" & System.Environment.CurrentDirectory & "\database.db") 
    Conn.Open() 
End Sub 

Private Shared Sub CloseConection(ByRef Conn As SQLite.SQLiteConnection) 
    Conn.Close() 
    Conn.Dispose() 
    Conn = Nothing 
End Sub 

Public Shared Function ReturnSelect(ByVal DataTAbleName As String, ByVal sQuery As String, ByVal sWhere As String) As Data.DataTable 
    Dim lDT As New DataTable 
    Dim lTA As New SQLite.SQLiteDataAdapter 
    If DataTAbleName Is Nothing Then Return New DataTable(DataTAbleName) 
    Try 
     OpenConection(conexion) 
     lTA = New SQLite.SQLiteDataAdapter("SELECT " & sQuery & " FROM " & DataTAbleName & IIf(sWhere <> String.Empty, " WHERE ", "") & sWhere, conexion) 
     lTA.Fill(lDT) 
    Catch ex As Exception 
     Throw ex 
    Finally 
     CloseConection(conexion) 
     lTA.Dispose() 
     lTA = Nothing 
    End Try 
    Return lDT 
End Function 

come cambiare che lavorare su un'architettura a 64 bit? Forse compresi 32 e 64 dll e nelle funzioni fare qualcosa di simile

Try 
    Instance = Me 
    'Check If Homidom Run in 32 or 64 bits 
    If IntPtr.Size = 8 Then _OsPlatForm = "64" Else _OsPlatForm = "32" 
    'continue code 

Catch ex As Exception 
    ' ex.Message 
End Try 

risposta

20

Esistono varie opzioni per l'utilizzo di SQLite da un assembly .NET. Il tuo primo passo è quello di passare a qualcosa di più recente rispetto all'antica versione 1.0.65. Le versioni attuali possono essere scaricate da qui: http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki o tramite lo SQLite NuGet packages.

Se è necessario essere in grado di eseguire sia a 32 bit che a 64 bit, un'opzione è utilizzare l'opzione di libreria nativa pre-caricamento, in cui si distribuiscono i binari nativi in ​​directory separate, in modo che assomiglia a questo:

  • \ App.exe (opzionale, gestito unica applicazione di montaggio eseguibile)
  • \ App.dll (opzionale, assemblaggio libreria di applicazioni gestito solo)
  • \ System.Data.SQLite .dll (richiesto, assembly principale solo gestito)
  • \ System.Data.SQLite.Linq.dll (opzionale, gestito solo LINQ assemblaggio)
  • \ x86 \ SQLite.Interop.dll (richiesta x86 assembly di interoperabilità nativa)
  • \ x64 \ SQLite.Interop.dll (richiesta x64 assembly di interoperabilità nativa)

Un'altra opzione è quella di costruire due versioni della tua app, e in ogni versione si fa riferimento l'assemblaggio modalità mista appropriata. Avresti quindi finito con due versioni, ma sono un po 'più semplici da gestire poiché non hai bisogno della sottodirectory extra e del file nativo * .Interop.dll.

In questi casi non sono necessarie differenze di codice o compilazione opzionale tra 32 e 64 bit. L'installazione dai diversi pacchetti NuGet probabilmente ti consentirà di iniziare più facilmente.

Un'ultima opzione è quella di andare per il clone gestito solo chiamato C# -SQLite: https://code.google.com/p/csharp-sqlite/. È una porta del motore SQLite per gestire C#, quindi l'intera cosa funziona come AnyCPU e il testimone non è un problema.

+0

Nota, ho dovuto trovare le DLL di interoperabilità nel file zip binario per il target .NET su cui sto lavorando. –

1

No non ce n'è uno.

Ecco perché questi * .dlls sono solo wrapper per c/C++ * .dll nativi. E un'applicazione a 32 bit, .NET deve usare la DLL a 32 bit c/C++ e un'applicazione a 64 bit, .NET deve usare la dll c/C++ a 64 bit.

Non ho usato vb.net per molto tempo, non sono sicuro che sia possibile configurare la piattaforma di destinazione come si può fare in C#. Se puoi, dovresti farlo e prendere la giusta DLL di interoperabilità. E dovresti decidere se hai bisogno di 32 o 64 bit.

+0

Quindi devo compilare due volte, una per 32 e altre per 64? – cMinor

+0

Sì, se si desidera fornire una versione a 32 e 64 bit. Perché se si imposta l'obiettivo su "qualsiasi CPU" verrà compilato per la versione di destinazione (64 o 32 dipende dalla finestra di destinazione). Devi impostare il tuo obiettivo su x86 (32 bit) o ​​su x64 (64 bit). – user743414

6

Ho avuto lo stesso problema qualche anno fa e per me la soluzione migliore è:

  • scaricare il latest version della biblioteca
  • nel tuo percorso bin messo solo il System.Data.SQLite.dll e alla fine System.Data.SQLite.Linq.dll
  • put la libreria x SQLite.Interop.dll in c:\Windows\SysWOW64
  • inserire la libreria x23 SQLite.Interop.dll in c:\Windows\System32
  • compilare il progetto come Any CPU riferimento solo System.Data.SQLite (la dll nel vostro percorso bin)
  • godono

In questo modo il framework .NET caricherà automaticamente il corretto (86 vs 64) libreria durante il runtime, senza registrando qualcosa in GAC o simili.

Spero che questo aiuti.

+1

Quale System.Data.SQLite.dll dovrei aggiungere alla cartella bin, x32 o x64 dll disponibili?Ho scaricato sia x32 che x64 e ogni versione ha System.Data.SQLite.dll e le loro dimensioni sono diverse .... – cMinor

+0

Mmm dovrebbero avere la stessa dimensione, quali versioni hai scaricato? –

+0

Ho scaricato i file .net 2, poiché la mia applicazione non può usare> .net 2. Sto facendo qualcosa di sbagliato? – cMinor

1

Le altre risposte qui da @Govert e @TobiaZambon sono la giusta via da seguire. Ma per chiunque altro la lettura, un'altra opzione è quella di utilizzare la versione x86 della DLL System.Data.Sqlite e compilare solo la tua applicazione per la piattaforma x86. Ad esempio, non compilare AnyCPU, il che significa che quando viene eseguito su macchine x64, la finestra verrà eseguita in modalità a 32 bit e sarà in grado di caricare la DLL a 32 bit.

Se questo è utile dipende dalla situazione, ma se si sta costruendo un'app distribuita su workstation è una soluzione piuttosto semplice.

1

Lo stato dell'arte della questione può essere facilmente risolto utilizzando Nuget dopo l'installazione, cercatela SQLite come:

PM> Install-Package System.Data.SQLite 

Ho fatto questo utilizzando un computer nuovo di zecca e VS, avevo bisogno di SQLite e ha fatto questo e tutto ha funzionato bene.