2013-08-16 26 views
12

Trước hết tôi cần nhấn mạnh rằng đây là câu hỏi hơi khác so với câu hỏi this thread . Ngoài ra, việc cài đặt KB2468871 không giúp ích gì."Không thể tải tệp hoặc lắp ráp 'System.Core, Version = 2.0.5.0, ..." ngoại lệ khi tải Thư viện lớp di động

Tôi đã cố gắng đơn giản hóa vấn đề này càng nhiều càng tốt. Nói chung nó về tải hội đồng PCL trong ứng dụng Desktop với Assembly.LoadFile (...).

Giả sử có một ứng dụng giao diện điều khiển .NET 4.0 (được gọi là "C"). Nó tham chiếu đến phiên bản .NET 4.0 (được gọi là "N4") và PCL assembly (được gọi là "PCL").

nơi N4 trông như thế này:

using System.Linq; 

namespace N4 
{ 
    public class ClassInN4 
    { 
     public static string Greet() 
     { 
      return new string(
       "hello from N4" 
       .ToCharArray() 
       .Select(char.ToUpper) 
       .ToArray() 
      ); 
     } 
    } 
} 

PCL trông như thế này:

using System.Linq; 

namespace PCL 
{ 
    public class ClassInPCL 
    { 
     public static string Greet() 
     { 
      return new string(
       "hello from pcl" 
       .ToCharArray() 
       .Select(char.ToUpper) 
       .ToArray() 
      ); 
     } 
    } 
} 

và C giống như thế này:

using System; 
using System.IO; 
using System.Reflection; 
using N4; 
using PCL; 

namespace C 
{ 
    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      Test(); 
      Console.ReadLine(); 
     } 

     private static void Test() 
     { 
      Test("N4", ClassInN4.Greet); 
      Test("PCL", ClassInPCL.Greet); 
     } 

     private static void Test(
      string title, 
      Func<string> generator) 
     { 
      try 
      { 
       Console.WriteLine(
        "{0}: {1}", title, generator()); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(
        "{0}: {1} -> {2}", title, e.GetType(), e.Message); 
      } 
     } 
    } 
} 

Khi bạn chạy ứng dụng này bạn sẽ có được hoàn toàn kết quả chính xác:

N4: HELLO FROM N4 
PCL: HELLO FROM PCL 

Hãy thêm sự kiện AssemblyResolve để CurrentDomain trong Program.Main:

AppDomain.CurrentDomain.AssemblyResolve += (_, a) => { 
    var fileName = Path.GetFullPath(
     new AssemblyName(a.Name).Name + ".data"); 
    Console.WriteLine("Probing '{0}'", fileName); 
    return 
     File.Exists(fileName) 
     ? Assembly.LoadFile(fileName) 
     : null; 
}; 

Vì vậy, những gì nó làm nếu lắp ráp không thể tìm thấy nó cố gắng để tải nó từ ".data" tập tin.

Hãy chuyển thư mục ứng dụng và đổi tên "N4.dll" thành "N4.data" và chạy "C.exe".

Probing 'C:\xxx\C\bin\Debug\N4.data' 
N4: HELLO FROM N4 
PCL: HELLO FROM PCL 

Vì vậy, nó đi qua AssemblyResolve và cuối cùng tải "N4.data" và hoạt động tốt như bản gốc.

Hãy trở lại "N4.data" thành "N4.dll" và đổi tên "PCL.dll" thành "PCL.data" và ...

Probing 'C:\xxx\C\bin\Debug\PCL.data' 
N4: HELLO FROM N4 
Probing 'C:\xxx\C\bin\Debug\System.Core.data' 
Probing 'C:\xxx\C\bin\Debug\System.Core.data' 
Probing 'C:\xxx\C\bin\Debug\System.Core.data' 
PCL: System.IO.FileNotFoundException -> Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified. 

Xin lưu ý rằng lắp ráp PCL đã được nạp tốt , vấn đề là, nó chỉ không thể tìm thấy phụ thuộc của nó (System.Core) nữa.

Giống như Assembly.LoadFile (tên tệp) là-no-no nếu lắp ráp được nạp là di động.

Có ai có vấn đề này không? Có ai đã giải quyết vấn đề này không?

Bạn có thể tìm thấy tất cả các tệp here.

EDIT: Nhờ leppie vì đã buộc tôi kiểm tra các tùy chọn khác. Tôi thực sự muốn chắc chắn rằng tôi không nói dối trong khi tôi trả lời "Yeah, yeah, tôi đã cố gắng". Rõ ràng nó là giá trị kiểm tra.

Từ Suzanne Cook's .NET CLR Notes:

Hãy cẩn thận - đây không phải là điều tương tự.

LoadFrom() đi qua Fusion và có thể được chuyển hướng đến một hội đồng khác ở một đường dẫn khác nhưng với cùng một danh tính đó nếu một đã được tải trong ngữ cảnh LoadFrom. LoadFile() không liên kết thông qua Fusion ở tất cả - bộ nạp chỉ tiếp tục và tải chính xác * những gì người gọi đã yêu cầu. Nó không sử dụng ngữ cảnh Load hoặc LoadFrom.

+4

Bạn đã thử 'Assembly.LoadFrom' hoặc tải nó dưới dạng mảng byte chưa? – leppie

+2

Tôi choáng váng. LoadFrom (...) hoạt động, trong khi LoadFile (...) thì không (btw, Load (byte []) cũng không hoạt động). Nếu bạn làm cho nó một câu trả lời tôi có thể cấp cho bạn một đánh dấu. Cảm ơn. –

+0

Trả lời câu hỏi của riêng bạn và nhận được một số đại diện, p – leppie

Trả lời

5

Bạn có thể trả lại lắp ráp System.Core của nền tảng của bạn (ví dụ version 4.0.0.0 for .NET Framework 4.0) từ sự kiện AssemblyResolve, khi được hỏi cho phiên bản 2.0.5.0.

Tôi tải tất cả các assembly tham chiếu của tôi được lưu trữ như các nguồn lực thông qua Load(byte[]), mà cũng không giải quyết được lắp ráp 2.0.5.0, và tôi lấy cả SystemSystem.Core từ AppDomain.CurrentDomain.GetAssemblies().

+0

Điều đó có ý nghĩa. Tôi đã không nghĩ rằng nó mặc dù, nhưng tôi không chắc chắn nếu nó sẽ làm việc như mong đợi trong kịch bản của tôi. AssemblyResolve có trong thư viện tái sử dụng (nhắm mục tiêu 4.0), nhưng ứng dụng chính có thể nhắm mục tiêu 4.5. Vì vậy, nếu các tài liệu tham khảo thư viện khác 2.0.5.0 tôi nên tải 4.0 hoặc 4.5. Làm thế nào để tôi biết từ thư viện mà ứng dụng chính là 4.5? Một câu hỏi khác là "để kết thúc những gì?". Hệ thống, System.Core, mscorlib, System.Xml, System.Data, System. 1 cho ý tưởng, nhưng không "trả lời đánh dấu" vì nó không làm cạn kiệt tất cả các câu hỏi. –

+0

@MiloszKrajewski, 'AppDomain.CurrentDomain.GetAssemblies()' cung cấp cho bạn các assembly chính xác và bạn không cần quan tâm đến .NET 4 hoặc 4.5. –

3

Tôi nghĩ rằng bạn đang nhận được những vấn đề này bởi vì:

Bạn đang nhận được một ngoại lệ bởi vì bạn không có các bản cập nhật mới nhất NET.

http://www.paraesthesia.com/archive/2013/01/21/using-portable-class-libraries-update-net-framework.aspx

Hãy chú ý của phần WSUS - bạn có thể nghĩ bạn có bản cập nhật mới nhất, nhưng bạn không gây WSUS server của bạn đã hết hạn.

vá này có thể giúp đỡ, nhưng bạn nên chỉ để có được tất cả các .net cập nhật:

http://support.microsoft.com/kb/2468871

(từ bình luận ở trên)

Hãy thử LoadFrom (...) thay vì LoadFile (...)/Load (byte []) và xem điều đó có khắc phục được sự cố của bạn không? :)

+1

Không. Tôi rõ ràng nói: "Ngoài ra, cài đặt KB2468871 không giúp đỡ.". Nó không phải là về cập nhật, nó chỉ là về cách sử dụng LoadFile(). –

+0

Hmmm ... Tôi đã gặp vấn đề tương tự với LoadFile() và sử dụng Windows Update để cài đặt tất cả các bản vá lỗi .net đã giải quyết nó cho tôi ... Chỉ cần kiểm tra, bạn có tất cả các bản vá .net (bắt buộc/tùy chọn) được cài đặt không ? –

+1

Đây là vấn đề của tôi, máy chủ chỉ có W2k8 SP1 và .NET 4.0 exe. Áp dụng các bản vá lỗi SP2 + đã sửa nó. – fiat

1

Tôi đã gặp sự cố tương tự và kết thúc bằng giải pháp sau: gọi mã sau đây trước khi tải linh hoạt lắp ráp PCL.

Assembly.Load("System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes"); 
Assembly.Load("System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes"); 

Nếu thiếu phụ thuộc khác khi bạn lắp ráp PCL, bạn chỉ cần thêm dòng để mã ở trên. Đối với một số lý do kỳ lạ và không thể hiểu được, nó hoạt động.

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