我有兩個版本的System.Data.SQLite.DLL - 適用於x86和x64平臺。 x86版本保留在應用程序文件夾中,x64版本保存在appFolder \ x64文件夾中。 編譯爲AnyCPU的應用程序。 如何根據Windows平臺加載所需的SQLite版本?加載x86或x64程序集
回答
如果您正在使用SQLite從http://system.data.sqlite.org,該System.Data.SQLite.DLL完全管理。有一個底層原生DLL,SQLite.Interop.DLL,需要根據進程(32位或64位)進行更改。
我部署在「\本地\ X64" 本地庫爲64位和」 \本地\ X86" 32位。在運行時P/Invoke SetDllDirectory設置DLL加載目錄指向進程的正確路徑。 http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx
(請注意,我不熟悉的傳統System.Data.SQLite.DLL版本從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);
您可以使用Environment.Is64BitProcess來將進程標識爲64位。 (我會盡量避免捕捉異常的流量控制儘可能。)
我很驚訝,這在所有工作。它應該首先找到x86版本並且失敗。一個失敗的程序集綁定不會通過AssemblyResolve產生另一個嘗試。
顯然,CLR實際上找不到x86版本,或者在x64模式下也會失敗。換句話說,當你解決這個問題時,你會破壞64位代碼。首先追蹤x86問題,使用Fuslogvw.exe查看該程序集正在探測哪些文件夾。
一個真正的修復應該包括將x86程序集移動到一個單獨的文件夾中,並相應地調整您的事件處理程序。您可以測試IntPtr.Size以確定您是否以64位模式運行(大小== 8)。此外,請確保生成完整的路徑名稱,使用現在使用的相對路徑可能會導致應用程序的工作目錄未設置在希望的位置。 Assembly.GetEntryAssembly()。位置爲您提供EXE的路徑。
- 在GAC中安裝相應的DLL(例如,64位版本在一個64位平臺上)
- 在你的web/app配置中使用程序集綁定(可能在機器配置中)
- 完全限定你的web/app配置中的任何部分程序集引用。
還有就是內置支持這1.0.80.0及更高版本。
如果開發和客戶機器可能有不同的處理器體系結構,可能需要多個二進制包。對於這種情況,強烈建議使用本機庫預加載功能。它從版本1.0.80.0開始可用,並且默認啓用。(from download page)
但是,要獲得它在我自己的工作插件我也有參考SQLite的首次之前,補充一點:
// 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...
看到這個問題:New SQLite mixed assemblies
一些反病毒程序阻止SetDllDirectory() - 花了很長時間才意識到這一點。 我們使用
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);
加載使用顯式路徑64 DLL。它在那個時候加載,並且.NET運行時將使用內存中的DLL,而不是在其中搜索磁盤。
Upvote for myass' :) – 2015-06-30 11:47:50
在我的情況下沒有工作。即使我已經使用調試器進行了驗證,但是本機庫可以正確加載。 SQLite仍然拋出關於本地DLL丟失的異常。 – BartoszKP 2016-12-13 15:22:20
我已經解決了這個問題。謝謝。我用「IntPtr.Size == 8」。我使用AppDomain.CurrentDomain.AssemblyResolve代替SetDllDirectory。 – Rover 2011-05-20 10:18:27