AppDomain.Load() - Laden einer Assembly nicht möglich

Norbert Eder

Erfahrenes Mitglied
Hallo!

Ich verwende das .NET Framework v2.0.50215 und versuche ein eine eigene AppDomain ein DLL-Assembly zu laden.

Das ganze sieht so aus, dass es sich um einen Application Server handelt, der in mehrere Projekte aufgeteilt ist. Ein Projekt enthält alle Klassen die auch für die Application die geladen werden soll von Relevanz ist (abstrakte Application-Klasse etc.).

Mein Problem ist nun, dass beim Laden der Assembly eine FileNotFoundException geworfen wird, die mir sagt, dass die Assembly oder eine Referenz nicht gefunden wurde.

Beides liegt jedoch im angegebenen Pfad und sollte vorhanden sein. Dabei scheint es auch vollkommen egal zu sein, ob die referenzierten Assemblies im GAC liegen oder im gleichen Verzeichnis der Application.

Folgender Code stellt einen meiner Versuche dar:

Code:
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = Path.GetDirectoryName(fullpath);
setup.ShadowCopyFiles = "yes";
setup.ShadowCopyDirectories = this.shadowPath;

Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence evidence = new Evidence(baseEvidence);

AppDomain newDomain = AppDomain.CreateDomain("TestDomain", evidence, setup);

Assembly assembly = newDomain.Load(this.ReadAssembly(fullpath));  // FileNotFoundException
Die Variable fullpath stellt hier den kompletten Pfad zur zu ladenden DLL dar. Die Methode ReadAssembly liest einfach nur die Assembly ein und gibt ein byte[] zurück. Hier nur anzumerken: Ich habe auch versucht die Assembly über
Code:
newDomain.Load(AssemblyName.GetAssemblyName(fullpath));
zu laden. Mit dem gleichen Erfolg.

Unter dem .NET Framework 1.1 ergeben sich keinerlei Probleme. Die MSDN gibt mir auch nicht besonderes viele Informationen dazu, da selbst Microsoft in den Beispielen zum 2.0er Framework mit den obsoleten Methoden arbeitet.

Hat hier irgendjemand eine Idee woran das liegen könnte?

Danke
 
Hat hier irgendjemand eine Idee woran das liegen könnte?
Evtl. am Framework 2.0 was immer noch BETA ist?
Wenn Du vor
Code:
newDomain.Load( AssemblyName.GetAssemblyName( fullpath ) );
ein
Code:
if ( File.Exists( fullpath ) ) );
und das Framework sie immer noch nicht findet,
kann es sichlich nicht an Dir liegen. :)

lg, cosmo
 
Das Problem ist ein anderes:

Die Methode AppDomain.Load hat sich von Version 1.1 auf Version 2.0 geändert. So wird hier die Assembly geladen und zurück an die ursprüngliche AppDomain gegeben. Dadurch entsteht auch das Problem, dass eine Referenz nicht geladen werden kann. In Version 2.0 ist diese Methode NICHT mehr dafür gedacht, eine Assembly in eine AppDomain zu laden. Nun gut. Pech würd ich mal sagen.

Das Problem daran ist jetzt folgendes:
Ich muss dynamisch Assemblies laden und wenn ich diese auch wieder unloaden möchte, müssen sie sich in einer eigenen AppDomain, quasi einer Remote-AppDomain befinden. Von Seiten Microsofts wird vorgeschlagen, das über CreateInstance zu machen, was allerdings ungut ist, denn erstens brauch ich dafür einen EntryPoint (den eine DLL ja nicht haben kann) ODER ich benötige den TypeName der Klasse die instanziert werden soll. Da dies jedoch ein dynamisches System ist, weiß ich diesen TypeName nicht, ohne die Assembly zu laden.

Tja und jetzt stellt sich die Frage wie ich das machen soll. Theoretisch könnte ich einen eigenen Prozess erstellen und statt DLLs EXEs verwenden, was ich allerdings nicht als schöne Lösung empfinde (immerhin muss ich das präsentieren, da es hierbei um meine Diplomarbeit geht) und scheidet mehr oder weniger aus. Eine andere Lösung hab ich dafür derzeit nicht.

@Cosmo:
Der Versuch mit File.Exists() war ganz nett, allerdings von der Theorie her zu weit unten angesetzt. Aber vielleicht hast du ja eine andere Idee.
 
Hallo!

...ODER ich benötige den TypeName der Klasse die instanziert werden soll.
Warum legst du nicht einfach in jeder Assembly eine Art Descriptor ab in dem du solche Meta-Informationen wie der entsprechende TypName der Klasse die instanziiert werden soll ab? Wenn du diesen immer gleich benennst (z.Bsp. plugin.xml ;-) ) kannst du sicherlich bequem in jedem Assembly danach suchen. (So macht das übrigens auch der Plugin Mechanismus der Eclipse-Plattform)

Gruß Tom
 
Norbert Eder hat gesagt.:
In Version 2.0 ist diese Methode NICHT mehr dafür gedacht, eine Assembly in eine AppDomain zu laden.
Das wusste ich noch nicht. :-(
Norbert Eder hat gesagt.:
Der Versuch mit File.Exists() war ganz nett, allerdings von der Theorie her zu weit unten angesetzt.
Daher dachte ich auch, dass die Methode evtl. Buggy ist.
Thomas Darimont hat gesagt.:
Warum legst du nicht einfach in jeder Assembly eine Art Descriptor ab in dem du solche Meta-Informationen wie der entsprechende TypName der Klasse die instanziiert werden soll ab? Wenn du diesen immer gleich benennst (z.Bsp. plugin.xml ) kannst du sicherlich bequem in jedem Assembly danach suchen. (So macht das übrigens auch der Plugin Mechanismus der Eclipse-Plattform)
Sehr interessant!
Vielen Dank für den Tipp, Thomas! :)

lg, cosmo
 
Prinzipiell ist es ja so, dass jede Assembly Metadaten besitzt. Das heißt, alle Typinformationen etc. können über die Assembly abgefragt werden. Dazu muss die Assembly allerdings geladen werden. Tue ich das, hab ich sie in der falschen AppDomain, was ich ja nicht will.

Eine Möglichkeit, die ich sehe, ist, dass der Entwickler ein Config-File zu seiner Applikation mit ablegt, die quasi den EntryPoint der Assembly beschreibt. Ansich wollte ich die Geschichte mit der Config anders lösen, aber das würde schon auch funktionieren. Erschwert es zwar ein wenig für den Entwickler, aber funktionieren würde es so (auch wenn es nicht besonders sauber ist).
 
Hallo,

könntest du bitte mal deinen Code schicken, wie du das Problem gelöst hast.
Habe nämlich das selbe Problem.

Danke!

Stefan
 
Ich hab den Code nicht da (der ist gut weggesperrt *g*), aber wenn ich nicht vergesse kann ich dir ein entsprechendes Beispiel erstellen.

Im Prinzip musst du die Assembly über einen remote Proxy laden, dann kannst du diese auch wieder entladen. Beispiele dazu sollten sich eigentlich finden lassen.
 
Hallo,

mich beschäftigt auch gerade die Frage, wie man eine Assembly über den Pfad in eine separate ApplicationDomain laden kann.

Ggf. führt es zum Erfolg den PrivateBinPath anzugeben und dort die zu ladende Assembly abzulegen, Beispiel:

Code:
AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationBase = "file:///" + System.Environment.CurrentDirectory;
 ads.PrivateBinPath = "bin";

AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);
ad2.Load("Name=myAssembly, culture=de-DE, Version=1.0, PublicKeyToken=4711");

Die Assembly sollte dann eigentlich im PrivateBinPath gefunden werden und über den qulifizierten Assemblyname gefunden und in die ApplicationDomain geladen werden können.

Habe das nicht ausprobiert und bin für weitere Kommentare dankbar.
 
Hi, sagt mal, ist das Thema noch aktuell Ich hab nämlich diesen Fehler auch und ich hab nen kurzes kleines Projekt geschrieben, das den Fehler reproduziert... Hat da nun schon jemand ne Lösung Oder ne Idee?
 
Zurück