2013-06-20 24 views
6

Jak utworzyć domenę aplikacji, dodać do niej złoenia, a następnie zniszczyć domenę aplikacji? To co próbowałem:Utwórz niestandardową domenę AppDomain i dodaj do niej złoenia.

static void Main(string[] args) 
    {   
     string pathToExe = @"A:\Users\Tono\Desktop\ConsoleApplication1.exe"; 

     AppDomain myDomain = AppDomain.CreateDomain("MyDomain"); 

     Assembly a = Assembly.Load(System.IO.File.ReadAllBytes(pathToExe)); 

     myDomain.Load(a.FullName); // Crashes here!    
    } 

Próbowałem również:

myDomain.Load(File.ReadAllBytes(pathToExe)); 

jak mogę dodać zespół do AppDomain. Raz ja, że ​​znajdę sposób poprzez odbicie go wykonać, a następnie zniszczyć AppDomain

wyjątkiem tego, że pojawia się:

Nie można załadować pliku lub zestawu „ConsoleApplication1, Version = 1.0.0.0, Kultura = neutralny, PublicKeyToken = null 'lub jedna z jego zależności. System nie może znaleźć określonego pliku.

+2

Łatwiej jest załadować montaż na własnej domenie - więc zamiast próbować montaż popchnąć do innej domeny rozważyć uruchomienie kodu w inna domena, aby załadować dowolny zestaw (nie zapomnij, że konieczne może być wstępne załadowanie zależności lub poprawne skonfigurowanie ścieżki wyszukiwania złożenia). –

+0

"Jedną z jego zależności" jest zwykle problem. Użyj Fuslogvw.exe, jeśli nie masz pojęcia, co to może być. I użyj AppDomainSetup, aby ustawić poprawną ścieżkę prywatną. –

Odpowiedz

11

Dwa szybkie punkty:

  1. AppDomain.Load ładuje montażowych w bieżącym AppDomain, a nie na myDomain (dziwne, wiem).
  2. AppDomain.Load ładuje zespół w kontekście Load, który usuwa złożenia z katalogów podstawowych aplikacji, ścieżek bin-prywatnych i GAC-a. Najprawdopodobniej zestaw, który próbujesz załadować, nie znajduje się w żadnej z tych lokalizacji, co wyjaśnia komunikat wyjątku.

Aby uzyskać więcej informacji, zapoznaj się z tym answer.

Jednym ze sposobów ładowania złożeń do elementu AppDomain jest utworzenie programu ładującego pochodnego MarshalByRef. Potrzebujesz czegoś takiego, aby uniknąć przeciekania typów (i złożeń) do głównej AppDomain. Oto prosta:

public class SimpleAssemblyLoader : MarshalByRefObject 
{ 
    public void Load(string path) 
    { 
     ValidatePath(path); 

     Assembly.Load(path); 
    } 

    public void LoadFrom(string path) 
    { 
     ValidatePath(path); 

     Assembly.LoadFrom(path); 
    } 

    private void ValidatePath(string path) 
    { 
     if (path == null) throw new ArgumentNullException("path"); 
     if (!System.IO.File.Exists(path)) 
      throw new ArgumentException(String.Format("path \"{0}\" does not exist", path)); 
    } 
} 

i używać go tak:

//Create the loader (a proxy). 
var assemblyLoader = (SimpleAssemblyLoader)myDomain.CreateInstanceAndUnwrap(typeof(SimpleAssemblyLoader).Assembly.FullName, typeof(SimpleAssemblyLoader).FullName); 
//Load an assembly in the LoadFrom context. Note that the Load context will 
//not work unless you correctly set the AppDomain base-dir and private-bin-paths. 
assemblyLoader.LoadFrom(pathToExe); 

//Do whatever you want to do. 

//Finally unload the AppDomain. 
AppDomain.Unload(myDomain); 
+0

Witam, po prostu próbowałem użyć twojej sugestii, aby wstępnie wczytać niektóre zespoły .net, aby dowiedzieć się, czy zawierają pewną implementację klasy interfejsu. Ale w przeciwieństwie do ładowania zestawu do bieżącej domeny, która działa dobrze, nie mogę załadować ich do mojej nowo utworzonej aplikacji AppDomain myDomain. –