I’m trying to finally get the Yats application to compile and run on both x86 and x64 Windows versions with a single build. The only library giving problems is System.Data.SQLite. I found an almost complete solution in stackoverflow. Here is a quick reminder on how to set up the Visual Studio project. I added the following code in my DAO class before starting to create any SQLite objects:
private static class NativeMethods { [DllImport("kernel32.dll", CallingConvention = CallingConvention.Cdecl)] internal static extern bool SetDllDirectory(string pathName); } public void Init() { // Underlying SQLite libraries are native. // Manually set the DLL load path according to the architecture var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Native"); if (IntPtr.Size == 8) // check for 32/64 bits { path = Path.Combine(path, "X64"); } else { // X32 path = Path.Combine(path, "X86"); } NativeMethods.SetDllDirectory(path); }
The SQLite libraries can be downloaded here. I use the sqlite-netFx35-binary-Win32-2008-1.0.84.0.zip and sqlite-netFx35-binary-x64-2008-1.0.84.0.zip. The ‘bundle’ packages do not contain the SQLite.Interop.dlls, not recommended in the download page.
The project directory structure after extracting the DLLs is:
Logging.SQLite (project directory) Native X64 SQLite.Interop.dll System.Data.SQLite.dll System.Data.SQLite.Linq.dll X86 SQLite.Interop.dll System.Data.SQLite.dll System.Data.SQLite.Linq.dll
The Visual Studio project properties for these DLLs are set to ‘Copy if newer‘. There is also a reference to one of the System.Data.SQLite.dll but I had to set the ‘Copy Local‘ property of the reference to false. Otherwise I get an exception during load: ‘The module was expected to contain an assembly manifest
‘. I will try to test this approach on more PCs and update this article if more problems are found.
Please leave a comment how it is working for you
UPDATE:
The SetDllDirectory does seem to fail. Another, very similar approach is to register an AssemblyResolve handler.
public void Init() { AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve; // do your SQLite init here AppDomain.CurrentDomain.AssemblyResolve -= OnAssemblyResolve; } private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs e) { if (e.Name.StartsWith("System.Data.SQLite,", StringComparison.OrdinalIgnoreCase)) { // Underlying SQLite libraries are native. // Manually set the DLL load path according to the architecture. var path = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Native"); if (IntPtr.Size == 8) // { path = Path.Combine(path, "X64"); } else { // X32 path = Path.Combine(path, "X86"); } string fileName = Path.Combine(path, "System.Data.SQLite.dll"); return Assembly.LoadFile(fileName); } return null; }
Nice article! I have been searching for a complete solution. Thanks