2014-07-21 15 views
5

Ho un servizio Windows che viene eseguito una volta al giorno. Sono solo 10 minuti di azione.Utilizzare l'assembly .NET senza bloccare il file dll

Costruisco i file del servizio nella cartella bin del sito Web, poiché il servizio utilizza le dll del sito Web.

Purtroppo ho notato che quando ho installato il modulo del sito Web (modulo dotnetnuke .zip dal programma di installazione del sito Web) ho ricevuto un errore che il file è stato bloccato da un processo antoher.

La disabilitazione del servizio prima che ciascun modulo sia installato è molto problematico, quindi voglio rendere il mio servizio non bloccare le DLL che sono utilizzate in esso.

Ho letto sulle opzioni AppDomain e ShadowCopyFiles, ma NON POSSO farle funzionare per me.

Questo è un esempio di come uso ShadowCopyFiles:

class Program 
{ 
    static string GenerateRandomName() 
    { 
     //maybe name must be unique?! 
     var random = new Random(); 
     return "a" + random.Next().ToString() + "b" + random.Next(); 
    } 

    static int RandomNumber() 
    { 
     var info = ConfigureAppDomainSettings(); 

     var domain = AppDomain.CreateDomain(GenerateRandomName(), null, info); 
     var assembly = domain.Load("SharedLibrary"); 
     var shared = (SharedLibrary.IShared)assembly.CreateInstance("SharedLibrary.Shared"); 

     int retVal = shared.RandomNumber(); 

     AppDomain.Unload(domain); 

     domain = null; 
     assembly = null; 
     shared = null; 
     info = null; 

     Console.WriteLine("before cleanning"); 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
     GC.WaitForFullGCComplete(); 
     GC.Collect(); 
     Console.WriteLine("after cleanning"); 

     return retVal; 
    } 

    static AppDomainSetup ConfigureAppDomainSettings() 
    { 
     AppDomainSetup domainSettings = AppDomain.CurrentDomain.SetupInformation; 
     domainSettings.ShadowCopyFiles = "true"; 
     domainSettings.CachePath = @"C:\inetpub\wwwroot\eshop\DesktopModules\Rossnet_EShop\SharedAssemblyTest\PrivateCache"; 

     return domainSettings; 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine(RandomNumber()); 

     Console.ReadKey(); 
    } 
} 

codice di esempio di montaggio:

public interface IShared 
{ 
    int RandomNumber(); 
} 

[Serializable] 
public class Shared : IShared 
{ 
    public int RandomNumber() 
    { 
     var random = new Random(); 
     return random.Next(20); 
    } 
} 

Una cache privata viene creato e non bloccato e il file originale viene bloccato. < - in questo momento questo è assurdo per me.

+0

L'interfaccia IShared viene caricata in entrambi i domini. Che mette un blocco permanente sulla DLL. Metti la classe condivisa in un'altra. –

+0

Ho eseguito il casting in tipo dinamico anziché in precedenza e non ha funzionato, quindi non è l'unico problema con il mio codice. –

risposta

8

Se si ha accesso a modificare tutto il codice che utilizza gli assembly, è sufficiente caricarli tramite il sovraccarico Assembly.Load che richiede uno byte[]. Leggerai tu stesso il file e passalo a quel metodo. Uso questo approccio personalmente (per altri motivi) e mi dà la possibilità di aggiornare i file in qualsiasi momento.

Un modo per farlo facilmente (anche se un po 'strano) è rinominare i file (da .dll in qualcos'altro, quindi non possono essere trovati) e quindi iscriversi all'evento AppDomain.AssemblyResolve, che verrà chiamato quando mancano, a quel punto è possibile avere il codice che carica manualmente gli assiemi.