2011-01-05 26 views
7

Tôi có một chương trình cần hoạt động trong cả môi trường x86 và x64. Nó đang sử dụng các trình điều khiển ODBC của Oracle. Tôi có một tham chiếu đến Oracle.DataAccess.DLL. DLL này là khác nhau tùy thuộc vào việc hệ thống là x64 hay x86, mặc dù.Cố gắng không cần hai giải pháp riêng biệt cho chương trình x86 và x64

Hiện tại, tôi có hai giải pháp riêng biệt và tôi đang duy trì mã trên cả hai. Điều này thật kinh khủng. Tôi đã tự hỏi giải pháp thích hợp là gì?

Tôi có nền tảng được đặt thành "Mọi CPU". và nó là sự hiểu biết của tôi rằng VS nên biên dịch DLL sang một ngôn ngữ trung gian như vậy mà nó không quan trọng nếu tôi sử dụng phiên bản x86 hoặc x64. Tuy nhiên, nếu tôi cố gắng sử dụng x64 DLL tôi nhận được lỗi "Không thể tải tập tin hoặc lắp ráp" Oracle.DataAccess, Phiên bản = 2.102.3.2, Văn hóa = trung lập, PublicKeyToken = 89b483f429c47342 'hoặc một trong những phụ thuộc của nó. để tải chương trình có định dạng không đúng. "

Tôi đang chạy trên một máy 32 bit, do đó, thông báo lỗi có ý nghĩa, nhưng nó khiến tôi tự hỏi làm thế nào tôi có nghĩa vụ phải phát triển hiệu quả chương trình này khi nó cần phải làm việc trên x64.

Cảm ơn.

+2

Nếu bạn sắp phát triển ứng dụng 32/64bit, bạn thực sự nên sử dụng hệ điều hành 64 bit. Ít nhất với Windows, một hệ điều hành 32 bit không thể chạy các chương trình 64 bit, nhưng một hệ điều hành 64-bit _can_ chạy các chương trình 32 bit. – rossipedia

+1

Một câu hỏi khác để suy ngẫm là "Ứng dụng của tôi * có thực sự * cần chạy trong 64 bit không?" WOW thực hiện một công việc tuyệt vời khi chạy một ứng dụng 32 bit trên x64. – vcsjones

Trả lời

0

Sử dụng AnyCPU với các kết buộc ban đầu sẽ không hoạt động, vì bạn cần hai giải pháp riêng biệt và xây dựng như bạn đã thấy. Bạn phải giữ hệ thống 64-bit để phát triển hoặc ít nhất là thử nghiệm các dll được biên dịch trên x64.

Tuy nhiên, với sự ràng buộc trễ, bạn có thể sử dụng thuộc tính AnyCPU và hệ thống để tìm hiểu kiến ​​trúc bạn đang chạy và liên kết với dll chính xác, nếu bạn giữ tên như Oracle.DataAccess.x86.dll. Nếu chúng được cài đặt vào GAC, nó thậm chí còn dễ dàng hơn, bạn có thể liên kết mà không cần phải thử nghiệm kiến ​​trúc trước, nhưng tôi tin rằng bạn vẫn phải ràng buộc muộn.

Lưu ý rằng VMware có thể chạy một khách 64 bit trên máy chủ 32 bit, nếu bạn thực sự không thể bị làm phiền khi cài đặt lại Windows.

2

Nếu bạn đang chạy trên máy 32 bit, thì bạn phải tải phiên bản 32 bit của Oracle DLL. Một chương trình 32 bit không thể tham chiếu đến một DLL 64 bit. Và, một chương trình 64 bit không thể tham khảo một DLL 32 bit.

"Bất kỳ CPU" nào là đích đúng nếu bạn có nhiều phiên bản của DLL bên ngoài. Bí quyết là đảm bảo rằng Oracle DLL thích hợp được đặt và tải. Đặt cược tốt nhất của bạn là tìm phiên bản 64-bit của DLL trên hệ thống 32-bit của bạn và đổi tên nó để thời gian chạy không thể tìm thấy nó.

+0

Tôi nghĩ chúng ta đang ở trong cùng một sân chơi bóng chày, nhưng ý nghĩ của tôi không được truyền đạt hoàn toàn đúng. Tôi đã tự bao gồm các dll 32bit thích hợp trong "giải pháp 32bit" của tôi và dll 64bit trong "giải pháp 64 bit". Khi tôi cần tạo các tập lệnh thực thi, tôi xây dựng cả hai giải pháp riêng biệt. Khi tôi đang phát triển tôi chỉ làm việc trong 32bit, và khi tôi kết thúc với những thay đổi mã của mình, tôi phải lặp lại những thay đổi đó trên giải pháp 64 bit. Tôi muốn chỉ sử dụng một giải pháp thay vì hai, nhưng có cùng kết quả. –

0

Bạn có thể định cấu hình cùng một giải pháp để tạo phiên bản x86/x64 riêng biệt. Bạn cũng có thể cần phải thêm các bước xây dựng bài đăng để sao chép phiên bản đúng của DLL vào các thư mục đầu ra tương ứng ...

Ít nhất nếu bạn phải xây dựng 2 giải pháp - sử dụng cùng một nguồn (thêm tệp như tham chiếu đến giải pháp thứ hai, không phải sao chép vào giải pháp thứ hai).

3

Đây hoàn toàn là vấn đề triển khai, bạn không bao giờ phải duy trì các dự án khác nhau. Đó là một trong những vụng về mặc dù, và boo trên Oracle vì không chăm sóc này. Một xem xét khác là lắp ráp này thực sự nên được ngen-ed trên máy mục tiêu. Một số tùy chọn

  • Tạo hai trình cài đặt, một cho x64 và một cho x86. Khách hàng chọn đúng sản phẩm, dựa trên hệ điều hành mà cô sử dụng. Đơn giản, bạn chỉ cần sao chép đúng tập tin.
  • Triển khai cả hai hội đồng với GAC. Bây giờ nó là tự động, NET chọn một trong những quyền trên một trong hai loại máy.Các công ty lớn nên hầu như luôn luôn sử dụng GAC để họ có thể triển khai các bản cập nhật bảo mật, không chắc tại sao Oracle không làm điều này.
  • Triển khai các hội đồng vào thư mục con x86 và x64 của thư mục cài đặt. Bạn sẽ cần phải viết một trình xử lý sự kiện AppDomain.AssemblyResolve, dựa trên giá trị của IntPtr.Size, chọn đúng thư mục.
  • Thay đổi nền tảng đích trên dự án EXE thành x86. Do mã của bạn cần phải hoạt động trên máy 32 bit cũng như trên máy tính 64 bit, không có/không phải là lý do để xây dựng cho AnyCPU.
3

Đây là một giải pháp làm việc cho vấn đề của bạn:

Thêm 2 DLL (x86 và x64) cho giải pháp của bạn trong một thư mục con. Đặt chúng thành "Sao chép nếu mới hơn"

Tham chiếu đúng DLL bạn sử dụng để phát triển gỡ lỗi từ 2 DLL bạn đã thêm vào. Làm cho nó Copy Local = false.

Điều này xảy ra khi bạn khởi động ứng dụng DLL không được tự động tải. Nó sẽ không được tải cho đến khi bạn sử dụng một loại từ hội đồng đó. Khi điều đó xảy ra, một sự kiện sẽ được kích hoạt trong .Net hỏi nơi có thể tìm thấy assembly của bạn.

Vì vậy, đôi khi trước lần sử dụng đầu tiên của hội đồng đó, hãy đảm bảo bạn đính kèm chính mình vào sự kiện đó.

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 

Trong nội dung của trình xử lý, hãy đảm bảo bạn tải DLL (x86 hoặc x64) khi nó yêu cầu.

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { 
     if (args.Name.Equals("MyFullAssemblyName")) { 
      var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 
      if (IntPtr.Size > 4) { 
       var dll = System.IO.Path.Combine(path, @"MySubDir\MyDLL_x64.dll"); 
       return System.Reflection.Assembly.LoadFile(dll); 
      } 
      else { 
       var dll = System.IO.Path.Combine(path, @"MySubDir\MyDLL.dll"); 
       return System.Reflection.Assembly.LoadFile(dll); 
      } 
     } 
     return null; 
    } 

Thì đấy. Bây giờ bạn có thể chạy ứng dụng của mình dưới dạng 32 bit và 64 bit.

Ngoài ra để thêm các file DLL trong một thư mục con, bạn có thể làm cho họ như nhúng Tài nguyên, và sau đó tải chúng như thế này:

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { 
     if (args.Name.Equals("MyFullAssemblyName")) { 
      var ass = Assembly.GetExecutingAssembly(); 

      if (IntPtr.Size > 4) { 
       var strm = ass.GetManifestResourceStream("the.resource.name.for.MyDLL_x64.dll"); 
       var data = new byte[strm.Length]; 
       strm.Read(data, 0, data.Length); 
       return Assembly.Load(data); 
      } 
      else { 
       var strm = ass.GetManifestResourceStream("the.resource.name.for.MyDLL.dll"); 
       var data = new byte[strm.Length]; 
       strm.Read(data, 0, data.Length); 
       return Assembly.Load(data); 
      } 
     } 
     return null; 
    } 

này không làm việc cho tất cả các cụm. Một số "hybrid" hội đồng có xu hướng thất bại, trừ khi chúng được nạp từ đĩa (có thể được giải quyết bằng cách viết chúng vào đĩa ngay trước khi tải).

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