Hello!
Egy olyan feladatot kellene végrehajtanom, hogy ASP.NET alatt be kellene töltenem különböző plugineket. Ez eddig még meg is van, de nekem ezeket a plugineket menet közben el is kell tudnom engedni, mivel frissíteni is kell őket. Na itt jön a feketeleves. Ugyebár, ha a fő appdomainba töltöm be, akkor nem tudom elengedni, csak ha újraindul az alkalmazás, ha a fájlt felülírom, akkor újraindul a webapp (webdevben biztosan).
Utánaolvastam a dolgoknak, és jó lenne külön appdomaint készíteni és abba betölteni (mindegyiket egy újba, mert ha belehívtam a dll-be, nem megengedhető, hogy leálljon az egész alkalmazás, vagy maga a dllben futó kód!) Viszont már az elsőt sem tudom betölteni. Ezzel próbálkozok:
AppDomainSetup domaininfo = new AppDomainSetup();
domaininfo.ApplicationBase = Server.MapPath("~") + "bin\\MeasurementDLLs";
AppDomain newDomain = AppDomain.CreateDomain(dll,null, domaininfo);
//newDomain.TypeResolve += ((s, a) =>
// {
// return System.Reflection.Assembly.LoadFrom(a.Name);
// });
newDomain.Load(File.ReadAllBytes(dll));
//System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(dll);
Ha megpróbálom betölteni, akkor File Not Found exception-t dob. Ha az eseményre feliratkozok, akkor a feliratkozáskor dob egy kivételt, pedig odáig már nem jutok el, hogy meg is próbáljam, hogy betöltsem a dll-t.
Jelenleg úgy épül fel a programom, hogy
- van egy dll, amiben benne van a webalkalmazásom. (betölti az IIS)
- van egy dll, amit a plugin íroi felé bocsájtok ki, hogy megfelelő interfészeket használják, melyek alapján a megfelelő osztályokat hasznlájam a plugin dllekből. Ez referálva van a webalkalmazásos dllben, ezért az IIS betölti a default appdomainbe.
- illetve van a harmadik, maga a plugin, amit szeretnék betölteni, de nem sikerül.
Ebben kérnék segítséget, hogy mit csinálok rosszul? Esetleg mit nem vettem észre.
Kerestem Google-n de pont ilyesmit nem találtam, a példakódok meg vagy nem fordultak le vagy ugyanúgy nem működött mint a sajátom.
Hozzászólások
Írj pontos exceptiont... És nem szép dolog bájtokból betölteni az assemblyt. Hivatkozz rá fájlnévvel. Nézegess fusion logot (fuslogvw.exe az SDK-ban).
--
Exception, ha nem vagyok az eseményre feliratkozva:
A(z) „ExamplePlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” fájl vagy szerelvény, illetve annak egyik függősége nem tölthető be. A rendszer nem találja a megadott fájlt.
Exception amikor feliratkozok az eseményre:
A(z) „WEBAPP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” fájl vagy szerelvény, illetve annak egyik függősége nem tölthető be. A rendszer nem találja a megadott fájlt.
Fontos, hogy a pluginekben nincs meghivatkozva a WEBAPP dll
Az appdomainnak hirtelenjében nem találtam meg azt a metódusát, hogy fájlnév alapján töltsön be. A DLL-eket egyelőre nem teszem a GAC-ba, és nem is nagyon szeretném.
Rossz a path, vagy nincs joga a processznek onnan beolvasni assembly-t.
Visual Studio, WebDev az én felhasználóm kontexusában fut. A projekt a saját dokumentumok mappámban van lementve, oda is fordul.
Biztos, hogy a kóddal van valami, de nem tudok rájönni, hogy mi az. Sajna a Google sem akar segíteni, pedig eddig puszipajtások voltunk :(
Tehát jó helyre mutat a változó, és nem dob ilyenolyan securityexceptionöket meg ilyesmit.
Nem dobál ilyesmi exceptiont.
Próbáltam használni a fusion viewertl de nem sok sikerrel. Semmit sem loggolt
És a fusion log mit mond? Assembly betöltés hibára ez AZ eszköz.
Szerk: Ja látom, próbáltad, de nem loggolt semmit. Futtatsd adminként, és a beállításaiban kapcsold be, hogy naplózzon, akkor fog. Meg egy iisreset sem árt.
--
- ha a \bin alá rakod a .dll-eket, mindig újra fog indulni az AppDomained ha változik (akkor is, ha sub-folderben vannak a cuccok)
- a FileNotFound exception alapján arra gondolnék, hogy itt még nincs semmi nagy mágia, egyszerűen rossz path-ről próbálod betölteni a .dll-t
Jelenleg úgy van megoldva, hogy a WEBAPP a bin könyvtárba fordul, úgy ahogy a fejlesztőknek szóló PluginDev is. a bin\measurementDlls mappába fordul az egy szem kísérleti pluginom.
Amikor a pluginokat be akarom tölteni akkor légyegében végig szaladok a measurementDlls mappán így:
így a dll változóban a teljes elérési útvonal benne lesz. Eddig úgy töltöttem be a dll-eket, és vettem ki belőlük a szükséges osztályokat, hogy
Ez szépen is működik csak nem lehet unloadolni az így betöltött DLL-t
De akkor átteszem, hogy a bin könyvtárral legyen egy szinten a plugin mappa
Szerk: áttettem máshová, átírtam az új appdomain path-jait
de a helyzet változatlan.
Szerk2: Mivel a plugin megreferálja a PluginDev dll-t ezért fordításkor a plugin mellé másolódik az is. De próbáltam azt is, hogy betöltöm a plugindevet előtte, de az sem volt neki elég. Továbbra is hiányolja a plugin dll-jét vagy annak valamilyen függőségét betöltéskor, akár byte[]-ként adom át, akár a nevével hivatkozok rá.
Illetve, ha megpróbálok feliratkozi az TypeResolve eseményre akkor a következő Exceptiont kapom:
Ennyire már nem ismerem a CLR-t, nem tudom, hogy most mit hiányolhat.
Nekem így működik:
Három project:
- Website (referenciálja IMyInterface-t tartalmazó projectet)
- IMyInterface-t tartalmazó project
- Plugin1-et tartalmazó project, Plugin1 MarshalByRefObject-ből származik (referenciálja IMyInterface-t tartalmazó projectet)
var domain = AppDomain.CreateDomain("MyDomain");
var instance = (IMyInterface) domain.CreateInstanceFromAndUnwrap(@"C:\pathtodll\TestClass.dll", "MyPlugins.Plugin1");
Irodalom:
http://www.brad-smith.info/blog/archives/500
Uhh, ütős egy anyag. Köszi. Remélem, hogy ASP.NET alá is át lehet ültetni.
Köszönöm, a példa lapján sikerült betöltenem, példányosítani, stb.
Az appdomainek közötti kommunikáció nagyon ineffektív, annyira, hogy érdemes megbarátkozni az apppool recyclevel.
Jelenleg ez egy kis egyetemi beadandó lenne, nem tervezem, hogy rendesen IIS alá telepítve fusson, így az Application Poolt nem igazán tudnám használni.
nem ide, csak a belépés gomb ide irányított :(