Laden...

DLL dynamisch laden

Erstellt von sylencer vor 19 Jahren Letzter Beitrag vor 18 Jahren 5.976 Views
S
sylencer Themenstarter:in
2 Beiträge seit 2005
vor 19 Jahren
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

X
2.051 Beiträge seit 2004
vor 19 Jahren

fällt es dir hier nix ein:

...From(@"C:sample.dll");
49.485 Beiträge seit 2005
vor 19 Jahren

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.

4.506 Beiträge seit 2004
vor 19 Jahren

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!”

S
sylencer Themenstarter:in
2 Beiträge seit 2005
vor 19 Jahren

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

142 Beiträge seit 2004
vor 19 Jahren

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! 😁

49.485 Beiträge seit 2005
vor 19 Jahren

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

1.373 Beiträge seit 2004
vor 19 Jahren

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

MfG VizOne

142 Beiträge seit 2004
vor 19 Jahren

@VizOne vielen Dank! 👍

Gruss, GIJOE

Auch Anfänger haben recht auf Leben! 😁

V
45 Beiträge seit 2004
vor 18 Jahren

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.

49.485 Beiträge seit 2005
vor 18 Jahren

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

V
45 Beiträge seit 2004
vor 18 Jahren

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.

N
4.644 Beiträge seit 2004
vor 18 Jahren

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 );
V
45 Beiträge seit 2004
vor 18 Jahren

Ä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.