Come scaricare un assembly dall'AppDomain principale?


38

Mi piacerebbe sapere come scaricare un assembly che viene caricato nell'AppDomain principale.

Ho il codice seguente:

var assembly = Assembly.LoadFrom(FilePathHere); 

ho bisogno/vogliono essere in grado di scaricare questa assemblea quando mi sono fatto.

Grazie per il vostro aiuto.

+1

Provare a non utilizzare LoadFrom, è in un contesto diverso rispetto al contesto di caricamento e può causare problemi. 24 set. 082008-09-24 01:09:32

  0

Buona domanda ma non riesco a vedere nessuna risposta chiara su come risolvere var assembly = Assembly.LoadFrom (FilePathHere); 13 lug. 122012-07-13 17:09:35

32

Non è possibile scaricare un assembly da un appdomain. Puoi distruggere le appdomain, ma una volta che un assembly viene caricato in un appdomain, è lì per la durata dell'appodain.

spiegazione di See Jason Zander di Why isn't there an Assembly.Unload method?

Se si utilizza 3.5, è possibile utilizzare il quadro di componente aggiuntivo per rendere più semplice la gestione/mettere in diverse AppDomain (che si può scarico, scarico tutte le assemblee) . Se si utilizzano versioni precedenti, è necessario creare una nuova appdomain per scaricarla.

  0

Ho pensato che fosse cambiato con .Net 3.5? 23 set. 082008-09-23 19:52:46

+1

Non ci sono piani per consentire lo scaricamento di un assembly da un dominio app (non me lo aspetterei neanche da uno, è molto difficile da fare e quelli che si preoccupano useranno una soluzione più sicura e più pulita). Il meglio che puoi fare è il codice gen leggero che Khoth ha citato 20 mar. 092009-03-20 14:46:17


14

Non è possibile scaricare un assieme senza scaricare l'intero AppDomain. Here's why:

  1. Si esegue il codice nel dominio app. Ciò significa che ci sono potenzialmente siti di chiamata e stack di chiamate con indirizzi che si aspettano di continuare a funzionare.

  2. Supponiamo di aver gestito tutti gli handle e i riferimenti a codice già in esecuzione da un assembly. Supponendo che non hai annullato il codice, una volta liberato correttamente l'assembly, hai solo liberato i metadati e IL. Il codice JIT è ancora allocato nell'heap del caricatore del dominio dell'app (i metodi JIT sono allocati sequenzialmente in un buffer nell'ordine in cui sono chiamati).

  3. Il problema finale riguarda il codice che è stato caricato condiviso, altrimenti formalmente conosciuto come "dominio neutrale" (check out/condiviso sullo strumento ngen). In questa modalità, il codice per un assembly viene generato per essere eseguito da qualsiasi dominio app (niente cablato).

Si consiglia di progettare l'applicazione intorno al limite del dominio dell'applicazione in modo naturale, dove lo scaricamento è completamente supportato.


4

Se si desidera avere un codice temporaneo che può essere scaricato in seguito, a seconda delle esigenze la classe DynamicMethod potrebbe fare ciò che si desidera. Questo però non ti dà lezioni.


8

È necessario caricare i componenti temporanei in un altro AppDomain e quando non in uso, è possibile scaricare quello AppDomain. È sicuro e veloce.

+2

Vedi AppDomain.DoCallback e vedi anche MarshalByRefObject: crei un "invoker" MarshalByRefObject con un metodo che fa ciò che vuoi e restituisce qualcosa nei suoi campi mutabili, tu crei un AppDomain temporaneo e chiama dom.DoCallback (invoker.DoSomething) per fare in modo che questo oggetto faccia ciò che vuoi; quindi raccogli i risultati da invoker nel tuo appdomain e scarica il dominio temporaneo. 19 lug. 112011-07-19 15:23:27

  0

@jkff: Sfortunatamente se si utilizza MarshalByRefObject, come nell'esempio PingPong, Assembly.LoadFrom verrà eseguito come nell'AppDomain principale, quindi lo scaricamento di AppDomain temp continuerà a generare il vecchio problema di non riuscire a scaricare l'assembly. Penso che potrebbe essere necessario serializzare in qualche modo i dati desiderati dall'AppDomain temp, senza il marshalling, se si desidera accedervi ed essere ancora in grado di scaricare l'assembly. 08 mag. 132013-05-08 16:30:37

  0

@jkff: Potresti avere ragione anche se ... ma non è così semplice come descritto nell'esempio MSDN. Probabilmente si dovrebbe usare tempAppDomain.CreateInstanceAndUnwrap ... e potrebbe essere necessario persino utilizzare AppDomain.GetData e SetData. (Questo non ingombrerà davvero l'appdomain se il suo scopo è solo quello di essere caricato e scaricato.) 08 mag. 132013-05-08 19:57:42


1

Ecco un buon esempio di come compilare ed eseguire DLL in fase di esecuzione e poi scaricare tutte le risorse: http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm


0

So che la sua vecchia, ma potrebbe aiutare qualcuno. Puoi caricare il file dallo stream e rilasciarlo. Ha funzionato per me. Ho trovato la soluzione HERE.

Spero che aiuti.


13

So anche che è molto vecchio, ma può aiutare qualcuno che sta avendo questo problema! Ecco un modo in cui ho trovato di farlo! invece di utilizzare:

var assembly = Assembly.LoadFrom(FilePathHere); 

uso questo:

var assembly = Assembly.Load(File.ReadAllBytes(FilePathHere)); 

Questo carica in realtà i "contenuti" del file di assiemi, invece del file stesso. Il che significa che NON è presente un blocco file sul file di assembly! Così ora può essere copiato, cancellato o aggiornato senza chiudere la tua applicazione o provare a utilizzare un AppDomain o un marshaling separati!

PRO: Molto semplice da risolvere con 1 riga di codice! CONS: Impossibile utilizzare AppDomain, Assembly.Location o Assembly.CodeBase.

Ora è sufficiente distruggere tutte le istanze create sull'assieme. Ad esempio:

assembly = null; 
  0

Con "** Can not use AppDomain **" vuoi dire che non puoi iniziarne uno all'interno di quell'assembly o potresti essere più specifico ? Che ne dite di 'AppDomain.CurrentDomain.Load (File.ReadAllBytes (FilePathHere));' C'è qualche differenza reale da Assembly.Load in questo specifico scenario? 23 ott. 162016-10-23 03:29:43


0

In alternativa, se il montaggio è stato appena caricato in primo luogo, per controllare le informazioni del complesso come la publicKey, il modo migliore sarebbe di non caricare, e piuttosto controllare la informazioni caricando solo l'AssemblyName all'inizio:

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe"); 
byte[] publicKey = an.GetPublicKey(); 
CultureInfo culture = an.CultureInfo; 
Version version = an.Version;