2013-08-16 7 views
12

Prima di tutto è necessario sottolineare che questa è una domanda leggermente diversa rispetto a quella in this thread . Inoltre, l'installazione di KB2468871 non è di aiuto."Impossibile caricare file o assembly" System.Core, Version = 2.0.5.0, ... "eccezione durante il caricamento dinamico della libreria di classi

Ho cercato di semplificare il più possibile questo problema. In generale si tratta di caricare gli assembly PCL nell'applicazione Desktop con Assembly.LoadFile (...).

Diciamo che c'è un'applicazione di console .NET 4.0 (chiamata "C"). Fa riferimento all'assembly .NET 4.0 (denominato "N4") e all'assembly PCL (denominato "PCL").

dove N4 si presenta così:

using System.Linq; 

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

PCL assomiglia a questo:

using System.Linq; 

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

e C simile a questa:

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

Quando si esegue questa applicazione si ottiene assolutamente risultati corretti:

N4: HELLO FROM N4 
PCL: HELLO FROM PCL 

Aggiungiamo evento AssemblyResolve a currentDomain in 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; 
}; 

Quindi, cosa fa se il montaggio non può essere trovato si cerca di caricarlo da file ".data".

Andiamo alla cartella dell'applicazione e rinominiamo "N4.dll" in "N4.data" ed eseguiamo "C.exe".

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

Quindi passa AssemblyResolve e infine carica "N4.data" e funziona come originale.

Diamo revert "N4.data" a "N4.dll" e Rinomina "PCL.dll" a "PCL.data" e ...

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. 

Si prega di notare che il PCL di assemblaggio è stato caricato più che bene il problema è che non riesce più a trovare le sue dipendenze (System.Core).

È come Assembly.LoadFile (fileName) è-un no-no se l'assembly caricato è portatile.

Qualcuno ha avuto questo problema? Qualcuno ha risolto questo problema?

È possibile trovare tutti i file here.

MODIFICA: Grazie a Leppie per costringermi a controllare altre opzioni. In realtà volevo essere sicuro di non mentire mentre rispondo "Sì, sì, ci ho provato". Apparentemente valeva la pena controllare.

Da Suzanne Cook's .NET CLR Notes:

Fare attenzione - questi non sono la stessa cosa.

LoadFrom() passa attraverso Fusion e può essere reindirizzato a un altro assieme su un percorso diverso ma con la stessa identità se uno è già caricato nel contesto LoadFrom. LoadFile() non esegue il binding tramite Fusion - il caricatore va semplicemente avanti e carica esattamente * ciò che il chiamante ha richiesto. Non utilizza il contesto Load o LoadFrom.

+4

Hai provato 'Assembly.LoadFrom' o lo hai caricato come array di byte? – leppie

+2

Sono stordito. LoadFrom (...) funziona, mentre LoadFile (...) no (btw, Load (byte []) non funziona neanche). Se lo fai una risposta, posso darti un segno di spunta. Grazie. –

+0

Rispondi alla tua stessa domanda e ricevi una risposta; p – leppie

risposta

5

è possibile restituire l'assemblaggio System.Core della piattaforma (ad esempio version 4.0.0.0 for .NET Framework 4.0) dall'evento AssemblyResolve, quando gli viene chiesto per la versione 2.0.5.0.

sto caricando tutti i miei gruppi di riferimento memorizzati come risorse tramite Load(byte[]), che non riesce a risolvere anche l'assemblaggio 2.0.5.0, ed a recuperare sia System e System.Core da AppDomain.CurrentDomain.GetAssemblies().

+0

Questo ha senso. Non l'ho pensato, ma non sono sicuro che funzionerà come previsto nel mio scenario. AssemblyResolve è nella libreria riutilizzabile (targeting 4.0), ma l'applicazione principale può essere scelta come 4.5. Quindi, se altri riferimenti bibliografici 2.0.5.0 dovrei caricare 4.0 o 4.5. Come faccio a sapere dalla libreria che l'applicazione principale è 4.5? Un'altra domanda è "a quale fine?". Sistema, System.Core, mscorlib, System.Xml, System.Data, System. ???. +1 per idea, ma nessun "tick risposta" in quanto non esaurisce tutte le domande. –

+0

@MiloszKrajewski, 'AppDomain.CurrentDomain.GetAssemblies()' fornisce gli assembly corretti e non è necessario preoccuparsi di .NET 4 o 4.5. –

3

penso che si stanno ottenendo questi problemi perché:

che stai ricevendo un'eccezione, perché non hai gli ultimi aggiornamenti .NET.

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

Prendere nota della parte WSUS - si potrebbe pensare di avere gli ultimi aggiornamenti, ma non causano il server WSUS non è aggiornato.

Questa patch può aiutare, ma sei meglio solo per ottenere tutti i .net aggiornamenti:

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

(da un commento precedente)

Prova LoadFrom (...) piuttosto che LoadFile (...)/Load (byte []) e vedere se questo risolve il problema? :)

+1

No. Ho esplicitamente detto: "Inoltre, l'installazione di KB2468871 non aiuta.". Non si tratta di aggiornamenti, si tratta solo di usare LoadFile(). –

+0

Hmmm ... Ho avuto lo stesso problema con LoadFile() e l'utilizzo di Windows Update per installare tutte le patch .net lo ha risolto per me ... Basta controllare, hai tutte le patch .net (richieste/facoltative) installate ? –

+1

Questo era il mio problema, server con solo W2k8 SP1 e .NET 4.0 exe. L'applicazione di patch SP2 + lo ha risolto. – fiat

1

Ho avuto lo stesso problema e ho trovato la seguente soluzione: richiamare il seguente codice prima di caricare dinamicamente l'assembly 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"); 

Se qualsiasi altra dipendenza manca quando si carica l'assembly PCL, è sufficiente aggiungere una riga al codice di cui sopra. Per qualche motivo strano e incomprensibile, funziona.

Problemi correlati