Laden...

DLL dynamisch laden

Letzter Beitrag vor 19 Jahren 14 Posts 6.101 Views
DLL dynamisch laden

Hi,

ich bin seit einigen Tagen dabei einen Windows-Dienst zu programmieren der dynamisch DLLs (in C# geschrieben) lädt. Um Fehler besser zu finden hab ich das erst in einem Consolenprog geschrieben.


Assembly SampleAssembly;
SampleAssembly = Assembly.LoadFrom(@"C:\sample.dll");
MethodInfo Method = SampleAssembly.GetTypes()[0].GetMethod("TestMethode");

string[] para = new string[2];

para[0] = "test";
para[1] = "test";

Method.Invoke(null,para);

wenn ich das in den Dienst einfüge, erhalte ich im EventLog folgende Fehlermeldung

System.ArgumentNullException: Wert darf nicht Null sein.
Parametername: assemblyFile
at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence)
at LoaderLib.Load.Loader()

d.h. es muss der Parameter Evidence mit irgendeinem "Beweis" gefüllt werden.

Dann gibt es noch die Möglichkeit mit dem DLLImporter eine DLL dynamisch zu laden. Die Beispiele die ich gefunden hatte beschrieben immer wie man in C geschriebe DLLs importiert. Ich habts dann mal probiert eine C# DLL zu importieren. Es geht alles soweit. Doch die Methode die ich angebe wird nicht gefunden...

Meine Frage nun: Wie kann ich dynamisch eine DLL in einem Windows-Dienst laden. Vielleicht weis jemand wie das Problem bei Assembly.LoadFrom gelöst werden kann. Wenn jemand die Testprogramme haben möchte, kann ich sie ihm zuschicken...

DANKE

fällt es dir hier nix ein:

...From(@"C:sample.dll");

Hallo Xqgene,

dass ist wohl dem Forumsparser geschuldet, der Backslashes verschluckt.

herbivore

Hinweis 08.04.2006: Der Forumsparser wurde geändert und zeigt die Backslashes nun wieder an.

Hallo!

Endlich mal ein Thema wo ich was dazu sagen kann!

Also Grundsätzlich kann man Methoden nur aufrufen, wenn die Klasse vorher instanziiert worden ist (Ausnahme static-Methoden).

Das funktioniert im Prinzip folgendermassen:


// assembly laden
Assembly myAssembly = Assembly.LoadFrom(@"C:\sample.dll");

// Klassentyp extrahieren
Type myClassType = myAssembly.GetType("Klassenname", true, true);

// Instanziieren der Klasse
// Für Klassen ohne Übergabeparameter im Konstruktor:
object myClass = Activator.CreateInstance(myClassType);

// Parameter für Methode definieren (hier einer, nämlich integer!)
object[] parameters = new object[1];
parameters[0] = (object) 4;

// Methode ausführen
object tmpObject = myClassType.InvokeMember("MethodenName",  System.Reflection.BindingFlags.InvokeMethod, null, myClass, parameters[]);

// Für einen Integer Rückgabewert dann unboxing:
int result = (int) tmpObject ;


Das sollte die Kurzanleitung für Reflection sein (die ich auch selbst nutze!).

Sollten Fragen hierzu sein, einfach posten.

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

Jo

aber ich hab das jetzt irgendwie hinbekommen. Hab eine neue Solution erstellt und alles noch mal neu gemacht. Und irgendwie funzt es jetzt. Ich werd mir aber deinen Beitrag noch mal grundlich durchlesen

Danke für eure Hilfe

Hallo @norman_timo!

Hab mal dein Demo ausprobiert.
Leider ohne Erfolg.

Wie bzw. wo bekomme ich den ClassenType her?

			// Klassentyp extrahieren
			Type myClassType = myAssembly.GetType("Class1");

Der bringt mir in myClassType immer "Nicht definierter Wert", was ja heist das er nix extrahiert.
Und wenn ich dann zu der nächsten Anweisung komme, sagt er mir "Der Wert darf nicht NULL sein"

			// Instanziieren der Klasse
			// Für Klassen ohne Übergabeparameter im Konstruktor:
			object myClass = Activator.CreateInstance(myClassType);

Vieleicht kannst du mir helfen?

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

Hallo GIJOE,

"Class1" ist einfach der Name der Klasse deren Methode du aufrufen willst. Setzte dafür einfach den Namen Deiner Klasse ein.

HTH

herbivore

Du musst den vollständigen Namen der Klasse angeben, also mit Namespace.

MfG VizOne

@VizOne vielen Dank! 👍

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

In welchem Format soll ich denn den Namespace (DieDLLNS) und die Klasse (DieDLLCL) übergeben?
Ich habe jetzt

Type myClassType = myAssembly.GetType(@"DieDLLNS.DieDLLCL", true, true);

genommen. Der Debuger schlägt immer in dieser Zeile Alarm.

Hallo velgreyer,

es sollte mit "DieDLLNS.DieDLLCL" gehen. Was schlägt der Debugger denn für einen Alarm?

Sorry, dass es jetzt dich trifft: Warum werden sehr oft die Fehlermeldungen/Exceptions nicht angegeben? Ihr könnt den Fehler nicht mit der Fehlermeldung finden, aber wir sollen es ohne können???

herbivore

Auch ein Sorry von mir, ich bin irgendwie der festen Überzeugung nachgegangen, dass ich den ersten Parameter falsch formatiert habe =)

Der Typ DieDLLNS.DieDLLCL in der Assembly DieDLL Version=1.0.2050.1845, Culture=neutral, PublicKeyToken=null konnte nicht geladen werden.

Hier mal ein Beispiel:

Assembly ass = Assembly.Load( "mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e0" );
Type myClassType = ass.GetType( "System.String" ); 
Console.WriteLine( myClassType.Name );

Ähem, ich hab den Fehler jetzt zwar nicht auffinden können, aber als ich einfach nur das Beispiel an meine DLL angepasst und erweitert habe, hat es funktioniert 🤔 Ende gut, Alles gut.

Danke sehr.