2013-05-04 20 views
8

Próbuję utworzyć aplikację z wtyczkami.FileNotFound przy ładowaniu złożenia z zależnością do innej domeny

Mam MainLib.dll, gdzie zrobiłem interfejs commnon (niech to będzie ICommon) z 1 metodą. Następnie zrobiłem 2 .dlls (wtyczki), które odwołują się do MainLib.dll i implementują ICommon w niektórych klasach. Ponadto usunąłem wszystkie odniesienia w tym pliku .dll z wyjątkiem System.

Potem stworzyliśmy aplikację, która monitoruje folderu ".\\Plugins" i ładuje wszystkie .dlls w newDomain należy sprawdzić, czy typy w .dll wdrożyć ICommon (tak, ta aplikacja również odwoływać się do MainLib.dll). Jeśli tak - dodaj nazwę .dll na jakiejś liście.

A teraz problem: przed Próbowałem załadować wtyczki - załadować MailLib.dll i system do newDomain ponieważ wszystkie wtyczki mają zależność ta .dlls. Ładują się poprawnie. Potem zacznę załadować wtyczki, a tu mam:

FileNotFoundException, nie można załadować pliku lub zestawu 'PluginWithException, Version = 1.0.0.0, Culture = neutral, TokenKluczaPublicznego = null' lub jeden z jego zależnościami. System nie może znaleźć określonego pliku.) Na łańcuchu Assembly loadedAssembly = domain.Load (Assembly.LoadFrom (asm) .FullName);

Zespół PluginWithException ma tylko 2 zależności - System i MainLib. Zanim spróbowałem załadować PluginWithException I sprawdził złożeń w nowej domenie, System i MainLib zostały załadowane do tej domeny. Więc nie widzę żadnych ploblemów z zależnością. Przeczytałem temat this i wypróbowałem rozwiązanie z ProxyDomain, ale wyjątek jest taki sam.

Co robię źle?

Oto kod:

public static List<string> SearchPlugins(string[] names) 
{ 
    AppDomain domain = AppDomain.CreateDomain("tmpDomain"); 
    domain.Load(Assembly.LoadFrom(@".\MainLib.dll").FullName); 
    domain.Load(@"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 
    MessageBox.Show(GetAssembies(domain)); // here I can see that System and MailLib exist in new domain 

    List<string> plugins = new List<string>(); 

    foreach (string asm in names) 
    { 
     Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName); // here I have exception 

     var theClassTypes = from t in loadedAssembly.GetTypes() 
          where t.IsClass && 
            (t.GetInterface("ICommonInterface") != null) 
          select t; 
     if (theClassTypes.Count() > 0) 
     { 
      plugins.Add(asm); 
     } 
    } 
    AppDomain.Unload(domain); 
    return plugins; 
} 

Odpowiedz

6

Nie określasz, w jaki sposób konfigurujesz ścieżki wyszukiwania dla aplikacji AppDomains, aby można było znaleźć biblioteki DLL w katalogu wtyczek, jednak Twój problem brzmi, jakby był bardzo podobny do tego, na który odpowiedziałem wczoraj:

AppDomain.Load() fails with FileNotFoundException

Może to również rozwiąże Twój problem? Daj mi znać, jak sobie radzisz.

+0

Dzięki! Twoja odpowiedź jest bardzo przydatna! Rozwiązanie z app.config działa, ale oboje wiemy, że nie jest to najlepszy sposób. Spróbowałem rozwiązania z ładowarką, uruchomiłem kod 'var plugins = loader.LoadPlugins ( Assembly.LoadFrom (Environment.CurrentDirectory + @" \ Plugins \ PluginWithOutException.dll "). FullName);' ale to nie pomogło :(Wyjątek jest taki sam :( –

+1

Czy próbowałeś skonfigurować ścieżkę PrivateBinPath dla potomnej AppDomain podczas jej tworzenia, aby wiedział, jak szukać w folderze wtyczek dla złożeń? Var appDomainSetup = new AppDomainSetup {PrivateBinPath = "Plugins"}; var domain = AppDomain.CreateDomain ("tmpDomain", AppDomain.CurrentDomain.Evidence, appDomainSetup); ' –

+0

Dziękuję! Próbowałem wcześniej rozwiązania z' PrivateBinPath', ale popełniłem błąd, teraz ładuje się i działa dobrze. ładowanie złożeń w nowych domenach, metoda wywołania interfejsu i rozładowywanie domen, sprawdziłem złożenia w bieżącej (domyślnej) domenie i niestety, były one załadowane w bieżącym (d efault). A rozwiązanie z app.config bez Loader ładuje również zespoły w domyślnej domenie. Czy to naprawdę możliwe, aby nie ładować tych złożeń w domyślnej domenie? –

2

Można powiedzieć domenę gdzie załadować zespoły z:

AppDomain domain = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins") });

Jednak nie widzę dlaczego ładujesz zespoły w bieżącej (domyślnej) domenie, a także w tmpDomain.

+1

Dzięki, wypróbowałem twój kod, ale wyjątek jest taki sam, w tej samej linii. Nie chcę ładować złożeń w domenie domyślnej, ponieważ nie chcę przechowywać śmieci w aplikacji (obraz, jeśli będzie to ponad 100 wtyczek), więc mogę załadować wtyczkę, użyć jej i wyrzucić ją z aplikacji, gdy Nie potrzebuję tego. –

+1

OK - ale kiedy wykonasz polecenie 'Assembly.LoadFrom (asm)' zostanie załadowane w bieżącej domenie. To pokonuje twój cel. Sugeruję, że masz klasę niestandardową 'PluginLoader' i ładujesz tę klasę w tmpDomain. Następnie możesz napisać kod w tej klasie, aby załadować wszystkie wtyczki za pomocą 'Assembly.LoadFrom' i zwrócić ci listę wtyczek, które chcesz. – YK1

+0

za pomocą eksploratora procesów sysinternals - w dowolnym momencie możesz znaleźć to, co jest załadowane w jakiej dziedzinie. – YK1