2010-09-24 32 views
12

Tôi có hai phiên bản System.Data.SQLite.DLL - cho x86 và x64. Phiên bản x86 giữ trong thư mục ứng dụng và phiên bản x64 giữ trong thư mục appFolder \ x64. Ứng dụng được biên dịch dưới dạng AnyCPU. Làm thế nào tôi có thể tải phiên bản SQLite cần thiết theo nền tảng windows?Đang tải x86 hoặc x64 assembly

Trả lời

17

Nếu bạn đang sử dụng SQLite từ http://system.data.sqlite.org, System.Data.SQLite.DLL được quản lý hoàn toàn. Có một DLL cơ bản, SQLite.Interop.DLL, cần phải thay đổi tùy thuộc vào quá trình (32 hoặc 64-bit).

Tôi triển khai các thư viện gốc trong ". \ Native \ X64" cho 64 bit và ". \ Native \ X86" cho 32 bit. Tại thời gian chạy P/Invoke SetDllDirectory để thiết lập thư mục tải DLL trỏ vào đường dẫn chính xác cho quá trình. http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx

(Lưu ý rằng tôi không quen với kiến ​​trúc của phiên bản di sản System.Data.SQLite.DLL từ 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

Tôi đã giải quyết vấn đề này. Cảm ơn. Tôi đã sử dụng "IntPtr.Size == 8". Tôi đã sử dụng AppDomain.CurrentDomain.AssemblyResolve thay vì SetDllDirectory. – Rover

1

Bạn có thể sử dụng Environment.Is64BitProcess để xác định quy trình là 64 bit. (Tôi sẽ cố gắng tránh bắt ngoại lệ như kiểm soát dòng chảy bất cứ khi nào có thể.)

+0

Đó là đề xuất tốt nhưng không giải quyết được sự cố của tôi. – Rover

+0

@Rover: Làm thế nào? Bạn chắc chắn đã cài đặt .NET 64 bit chưa? –

+0

Tôi sử dụng .NET 3.5 không có biến này. Tôi nghĩ rằng tôi có thể kiểm tra phiên bản của nền tảng nhưng nó chỉ tránh bắt một số trường hợp ngoại lệ nhưng lắp ráp cần thiết không được nạp. – Rover

0

Bạn không thể sử dụng nguồn của SQLite như một dự án riêng biệt trong giải pháp thay vì lắp ráp sẵn? Sử dụng AnyCPU bản thân hệ thống sẽ xử lý tất cả mọi thứ và bạn không phải làm điều đó trong mã ...

+0

Đó là một trong những dll mà tôi sử dụng chia cho x86 và x64. Tôi không có mã nguồn của tất cả các dll được sử dụng. – Rover

+0

Điều này sẽ không giải quyết được vấn đề gì cả, vì kiến ​​trúc của máy phát triển không phải lúc nào cũng giống như máy triển khai. Bất kỳ CPU nào chỉ hoạt động cho các assembly .NET, không phải cho các DLL nguyên thủy (sử dụng SQLITE phù hợp dưới mui xe) – BigBoss

3

Tôi ngạc nhiên vì điều này có hiệu quả. Nó sẽ tìm phiên bản x86 trước và thất bại. Một ràng buộc lắp ráp không thành công không tạo ra một nỗ lực khác thông qua AssemblyResolve.

Rõ ràng, CLR không thể tìm thấy phiên bản x86 hoặc điều này cũng sẽ không thành công ở chế độ x64. Nói cách khác, khi bạn khắc phục sự cố, bạn sẽ phá vỡ mã 64 bit. Theo đuổi vấn đề x86 đầu tiên, hãy sử dụng Fuslogvw.exe để xem các thư mục nào đang được thăm dò cho assembly.

Sửa lỗi thực tế phải bao gồm di chuyển cụm x86 vào một thư mục riêng biệt và điều chỉnh trình xử lý sự kiện của bạn cho phù hợp. Bạn có thể kiểm tra IntPtr.Size để tìm hiểu xem bạn đang chạy ở chế độ 64-bit (Size == 8). Ngoài ra hãy chắc chắn để tạo ra một tên đường dẫn đầy đủ, bằng cách sử dụng đường dẫn tương đối như bạn làm bây giờ có thể gây ra thất bại khi thư mục làm việc của ứng dụng không được thiết lập nơi bạn hy vọng nó được. Assembly.GetEntryAssembly() Vị trí giúp bạn có được đường dẫn của EXE.

+0

Tôi đã xóa mã để tránh nhầm lẫn và chỉ để lại câu hỏi. – Rover

+0

Hmm, tôi không nghĩ rằng thay đổi câu trả lời của tôi. Đoạn cuối cùng cho bạn biết cách làm đúng. –

+0

Ok, tôi kiểm tra nền tảng, tìm thấy lắp ráp cần thiết. Tôi nên làm gì để tải assembly vào AppDomain? – Rover

0
  1. cài đặt DLL thích hợp trong GAC (ví dụ như phiên bản 64bit trên nền tảng 64bit)
  2. sử dụng ràng buộc lắp ráp trong cấu hình web/ứng dụng của bạn (có thể trong cấu hình máy)
  3. Hoàn toàn đủ điều kiện tham chiếu lắp ráp một phần trong cấu hình web/ứng dụng của bạn.
5

Có hỗ trợ tích hợp cho điều này trong 1.0.80.0 trở lên.

Nếu máy phát triển và máy khách có thể có kiến ​​trúc vi xử lý khác nhau, có thể yêu cầu nhiều hơn một gói nhị phân. Đối với trường hợp này, sử dụng tính năng tải trước thư viện gốc gốc được khuyến nghị. Nó có sẵn như là phiên bản 1.0.80.0 và được kích hoạt theo mặc định.(from download page)

Tuy nhiên, để có được nó để làm việc trong riêng tôi plug-in Tôi cũng đã có thêm điều này trước khi tham khảo SQLite cho lần đầu tiên:

// 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... 

Xem câu hỏi này: New SQLite mixed assemblies

11

Một số progs chống virus ngăn chặn SetDllDirectory() - đã cho tôi một thời gian dài để nhận ra điều đó. Chúng tôi đang sử dụng

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); 

để tải x64 DLL có đường dẫn rõ ràng. Nó được nạp vào thời điểm đó và .NET Runtime sẽ sử dụng DLL trong bộ nhớ thay vì tìm kiếm đĩa cho nó.

+5

Upvote cho 'myass' :) –

+0

Không hoạt động trong trường hợp của tôi. Mặc dù tôi đã xác minh với trình gỡ lỗi, rằng thư viện gốc được tải chính xác. SQLite vẫn ném một ngoại lệ về DLL bản địa bị thiếu. – BartoszKP

Các vấn đề liên quan