I have two versions of System.Data.SQLite.DLL - for x86 and x64 platform. The x86 version keeps in application folder and x64 version keeps in appFolder\x64 folder. The application compiled as AnyCPU. How can i load needed version of SQLite according to windows platform?
7 Answers
If you are using SQLite from http://system.data.sqlite.org, the System.Data.SQLite.DLL is completely managed. There is an underlying native DLL, SQLite.Interop.DLL, that needs to change depending on the process (32- or 64-bit).
I deploy the native libraries in ".\Native\X64" for 64-bit and ".\Native\X86" for 32-bit. At runtime P/Invoke SetDllDirectory to set the DLL load directory pointing at the correct path for the process. http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx
(Note that I'm not familiar with the architecture of the legacy System.Data.SQLite.DLL version from 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);

- 6,204
- 5
- 29
- 29
-
3I've solved this problem. Thanks. I used "IntPtr.Size == 8". I used AppDomain.CurrentDomain.AssemblyResolve instead of SetDllDirectory. – Rover May 20 '11 at 10:18
Some antivir progs prevent SetDllDirectory() - took me a long time to realize that. We are using
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);
to load the x64 DLL with explicit path. It is loaded at that point and the .NET Runtime will use the in-memory DLL instead of searching the disk for it.

- 129
- 1
- 2
-
Didn't work in my case. Even though I've verified with the debugger, that the native library gets correctly loaded. SQLite still throws an exception about native DLL missing. – BartoszKP Dec 13 '16 at 15:22
There is built-in support for this in 1.0.80.0 and later.
If the development and customer machines may have different processor architectures, more than one binary package may be required. For this situation, using the native library pre-loading feature is highly recommended. It is available as of version 1.0.80.0 and enabled by default. (from download page)
However, to get it to work in my own plug-in I also had to add this before referencing SQLite for the first time:
// 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...
See this question: New SQLite mixed assemblies
I'm surprised that this works at all. It should find the x86 version first and fail. A failed assembly bind doesn't produce another attempt through AssemblyResolve.
Clearly, the CLR cannot actually find the x86 version or this would fail in x64 mode as well. In other words, when you fix the problem, you'll break the 64-bit code. Chase the x86 problem first, use Fuslogvw.exe to see which folders are being probed for the assembly.
A real fix should include moving the x86 assembly into a separate folder as well and adjusting your event handler accordingly. You can test IntPtr.Size to find out if you're running in 64-bit mode (Size == 8). Also be sure to generate a full path name, using the relative path like you do now can cause failure when the app's working directory isn't set where you hope it is. Assembly.GetEntryAssembly().Location gets you the path of the EXE.

- 922,412
- 146
- 1,693
- 2,536
-
-
Hmm, I don't think that changes my answer. The last paragraph tells you how to do it right. – Hans Passant Sep 24 '10 at 14:17
-
Ok, i checked platform, found needed assembly. What should i do for loading of assembly to AppDomain? – Rover Sep 24 '10 at 14:32
-
You mean you want to load it in a non-default AppDomain? Better start a new question for that. – Hans Passant Sep 24 '10 at 16:17
You could use Environment.Is64BitProcess to identify the process as 64 bit. (I would try to avoid catching exceptions as flow-control wherever possible.)

- 37,459
- 12
- 63
- 82
-
-
I use .NET 3.5 that not have this variable. I think i can check the version of platform but it only avoid catching some exceptions but needed assembly is not loaded. – Rover Sep 24 '10 at 13:55
-
@Rover: Ah hah, I am with you now. You are saying that the 64 bit assembly fails to load on 64 bit platform, rather than that you don't know how to detect the local platform? – Paul Ruane Sep 24 '10 at 14:11
-
-
@Rover: OK, would it not be possible to check the Environment.Is64BitProcess and then, depending upon the result, load either the 32 bit library (Environment.Is64BitProcess = false) or the 64 bit library (Environment.Is64BitProcess = true)? – Paul Ruane Sep 24 '10 at 14:26
-
Couldn't you just use the source of SQLite as a separate project in your solution instead of a precompiled assembly? Using AnyCPU the system itself will take care of everything and you don't have to do it in code...

- 2,225
- 2
- 27
- 39
-
It's one of dlls that i use which divided on x86 and x64. I don't have source code of all used dlls. – Rover Sep 24 '10 at 13:31
-
This won't solve any problem at all, since the architecture of development machine is not always same as deployment machine. Any CPU only work for .NET assemblies, not for native DLLs(witch SQLITE use under the hood) – BigBoss Oct 05 '13 at 10:00
- install appropriate DLL in the GAC (e.g. 64bit version on a 64bit platform)
- use assembly binding in your web/app configuration (possibly in machine config)
- Fully qualify any partial assembly references in your web/app config.

- 3,698
- 1
- 26
- 52