Laden...

Parameter Count aus einer DLL Methode

Erstellt von Nejox vor 2 Jahren Letzter Beitrag vor 2 Jahren 455 Views
N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren
Parameter Count aus einer DLL Methode

Hallo zusammen,

ich bin mir gerade nich sicher wonach ich Suchen soll. Ich wollte mal in Erfahrung bringen ob es möglich ist die Anzahl von Parametern aus einer DLL Methode zu bekommen?

Ich habe folgenden Code


public class MyClass
{
        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern IntPtr LoadLibrary(string library);

        [DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string methodName);

        public void LoadDll()
       {
           IntPtr module = LoadLibrary("myDll");

           // Fehler behandlung wenn DLL nicht gefunden wurde
            if (module == IntPtr.Zero)
            {
                return $"Could not load library: {Marshal.GetLastWin32Error()}";
            }

            IntPtr dllMethod = GetProcAddress(module, "myFunction");

            // Fehler behandlung wenn Methode in der DLL nicht gefunden wurde
            if (dllMethod== IntPtr.Zero)
            {
                return $"Fehler beim Laden der DLL Methode { Marshal.GetLastWin32Error() }";
            }

             // Hier möchte ich nun abfragen wieviel Parameter in der dll Methode "myFunction" vorhanden sind.
        }
}

Freue mich auf eine Antwort 🙂

4.938 Beiträge seit 2008
vor 2 Jahren

Das ist technisch nicht möglich. Die Parameter von nativen (z.B. in C oder C++ geschriebenen) Funktionen werden über den Stack (welches einfach nur ein Byte-Array darstellt) übergeben und ausgelesen. Genausowenig ist es daher möglich die genauen Datentypen der Parameter abzufragen, ohne den Code zu kennen. Daher ist es zur Verwendung zwingend nötig, die genaue Signatur der Funktion zu kennen.

Anders sieht es bei .NET aus, da diese mittels Reflection erfragt werden können.

C
55 Beiträge seit 2020
vor 2 Jahren

Wenn du wirklich ein Plugin System bastelen möchtest, dann solltest du dir noch mal Gedanken über dein Konzept machen. So wie das aktuell ist, kann es nur nach hinten losgehen.

Dein Plugin sollte eine Schnittstelle haben, die das Programm, welches das Plugin nutzen möchte eindeutig versteht. Das kann man Besten über ein Interface machen, das dein Plugin implementiert und dein Programm laden kann. Dann musst auch nicht mehr die Parameter herausfinden, da alles mit einer eindeutigen Schnittstelle bekannt sein sollte für beide Seiten.

Hier noch etwas ausführlicher:
Erstellen einer .NET Core-Anwendung mit Plug-Ins - .NET

N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren

Danke für die Antworten.

@ClaraSoft
Hättest du hier mal ein Beispielprogramm? Kann mir das ehrlich gesagt noch nicht so richtig vorstellen.

C
55 Beiträge seit 2020
vor 2 Jahren

Steht alles im Link beschrieben, den ich gepostet habe.

N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren

Ah sorry habs gerade geshen 🙂
Danke.

4.938 Beiträge seit 2008
vor 2 Jahren

Das funktioniert aber nur für .NET-Assemblies, nicht für native DLLs.

Oder ist "myDll" gar keine native DLL und du hast nur die falsche Methode zum Laden benutzt?

C
2.121 Beiträge seit 2010
vor 2 Jahren

Mal angemerkt, selbst wenn man rausfinden könnte wie viele Parameter eine Methode/Funktion hat, weiß man ja immer noch nicht welche das sind.
Würde also nicht sehr viel bringen, denn man hat dann immer noch keinen Hinweis darauf was man da nun übergeben soll.

N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren

MyDll ist eine Fremd Dll auf C bzw. C++ Basis soweit ich weiß.

N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren

Wenn du wirklich ein Plugin System bastelen möchtest, dann solltest du dir noch mal Gedanken über dein Konzept machen. So wie das aktuell ist, kann es nur nach hinten losgehen.

Dein Plugin sollte eine Schnittstelle haben, die das Programm, welches das Plugin nutzen möchte eindeutig versteht. Das kann man Besten über ein Interface machen, das dein Plugin implementiert und dein Programm laden kann. Dann musst auch nicht mehr die Parameter herausfinden, da alles mit einer eindeutigen Schnittstelle bekannt sein sollte für beide Seiten.

Hier noch etwas ausführlicher:

>

Ich wollte nochmal nachfragen ob du davon ausgegangen bist das "myDll" eine dll von mir ist?
Wenn ja, ist sie nicht. Sorry für das Missverständniss. Hätte es dann anders benennen sollen. Ich muss damit arbeiten und kann auch nichts an der "myDll" ändern.

4.938 Beiträge seit 2008
vor 2 Jahren

MyDll ist eine Fremd Dll auf C bzw. C++ Basis soweit ich weiß.

Dann sollte es dafür doch eine zugehörige Headerdatei (.h oder .hpp) geben, in der die Funktionen deklariert sind. Die Aufrufe mußt du dann nur per "Marshalling" nach C# übertragen (also so wie du es bisher auch für die Funktionen LoadLibrary und GetProcAddress per DllImport gemacht hast) - du mußt die DLL also nicht dynamisch laden (außer du willst wirklich ein Plugin-System realisieren, d.h. beliebig benannte DLLs mit einheitlicher Schnittstelle aufrufen zu können).

s.a. Verwenden nicht verwalteter DLL-Funktionen

N
Nejox Themenstarter:in
19 Beiträge seit 2016
vor 2 Jahren

Ich möchte das ganze eher Dynamisch händeln. Der Grund ist das es mehrere Versionen von der aufzurufenden DLL gibt. Hier muss ich bestimmte Unterscheidungen machen was für eine Version genutzt werden soll. Sonst müsste ich ja jede einzelne DLL als DLL Import definieren. Oder sehe ich das falsch?

Hinweis von Abt vor 2 Jahren

Bitte keine Full Quotes.

2.079 Beiträge seit 2012
vor 2 Jahren

Das geht nicht dynamisch, irgendwo brauchst Du einen gemeinsamen Stand, anhand dessen Du weißt, wie Du XY aufrufen kannst.
Hast Du diesen gemeinsamen Stand nicht, musst Du wohl oder übel alles einzeln machen.
Oder Du rätst, was es für Parameter gibt, wirst dann aber ziemlich sicher irgendwann den Fall haben, dass Du die richtigen Parameter nicht errätst.

Deshalb sollte man das auch umdrehen:
Nicht dein Programm muss die externe DLL und die Parameter der Methoden kennen, sondern die externe DLL kennt dein Programm.
Dein Programm liefert dafür dann eine Schnittstelle, die die externe DLL nutzt - das ist dein gemeinsamer Stand.

Du könntest also ein Interface definieren, wo die Methode, die Du brauchst, definiert ist und als Parameter wird alles übergeben, was Du bieten kannst/darfst.
Die externe DLL muss dann dieses Interface implementieren und kann dann die Daten so weiter reichen, wie es für die jeweilige Version richtig ist.
Diese Implementierung findest Du dann via Reflection oder einer Art Registrierungs-Interface, was aber auch wieder implementiert und irgendwie gefunden werden muss.
Dein Programm bekommt dann die Implementierung und hat ein eindeutiges Interface zum Aufrufen.

Bei externen DLLs geht das natürlich nicht so einfach, da brauchst Du denn einen Vermittler dazwischen - je Version.
Dieser Vermittler implementiert dein Interface und ruft darin die externe Version auf, der muss dann immer angepasst werden, dein Haupt-Programm bleibt dabei aber unberührt.
Der Vermittler kann in C# oder C++/CLI geschrieben werden, je nachdem, was einfacher ist, hauptsache es kommt eine managed DLL bei raus.
Du kannst natürlich auch unmanaged arbeiten, kannst dann aber nicht mit .NET-Interfaces arbeiten und musst irgendwie anders die native Methode definieren, die dein Programm aufruft.

Der Nachteil ist, dass Du je Version eine zusätzliche DLL brauchst, aber je nach Umfang der externen Methoden ist das nur sehr wenig Arbeit.
Außerdem sehe ich das nicht als Nachteil, sondern als Vorteil, denn Du hast einen einzigen Punkt, den Du anpassen musst und gefährdest dein restliches Programm nicht.
Die könnte man z.B. sogar zur Laufzeit austauschen oder als einzige DLL raus geben, ohne das ganze Programm aktualisieren zu müssen.

4.938 Beiträge seit 2008
vor 2 Jahren

Verstehe ich das richtig, daß du daher aufgrund deiner Frage zur Parameteranzahl damit herausfinden möchtest, um welche Version es sich handelt?
Das ist, wie schon geschrieben, so nicht möglich.

Und beim Aufrufen der Funktionen per dynamischen Laden müßtest du ja sowieso Marshal.GetDelegateForFunctionPointer (LOL: "marshal" wird als "Mars Hallen" übersetzt) benutzen und dafür dann je nach Funktionsvariante passende Delegates erzeugen.

Du solltest einfach alle Funktionsvarianten (welche du in deinem Programm auch aufrufen möchtest) per DllImport erzeugen (ich nehme an, die DLL hat immer denselben Namen). Du mußt dann nur in deinem Programm eine passende Logik einbauen, welche die verschiedenen Versionen erkennt (evtl. die Datei-Info auslesen?) und dementsprechend dessen Funktionsvarianten aufruft.

Warum gibt es überhaupt verschiedene Versionen der DLLs, die dein Programm unterstützen soll?

16.827 Beiträge seit 2008
vor 2 Jahren

Sonst müsste ich ja jede einzelne DLL als DLL Import definieren. Oder sehe ich das falsch?

Mir ist auch immer noch völlig unklar, was Du tun willst; was Du mit dynamisch meinst.

Soll Deine Anwendung einfach prinzipiell verschiedene Versionen einer Abhängigkeit unterstützen, oder sollen diese auch noch dynamisch während der Laufzeit ausgetauscht werden?
Beides ist prinzipiell (mit unterschiedlichem Aufwand) umsetzbar; aber in allen Fällen würde man das nicht versuchen mit schwarzer Magie sondern mit strukturierten Vorgehen lösen wollen.

Fixe Version während der Runtime: kann man über eine klassische 0815 Pluginstruktur lösen.
Austausch während der Runtime: in .NET Core 3+ / .NET 5 gar nicht so einfach zu lösen, da es keine App Domains mehr gibt; der AssemblyLoadContext bietet aber grundlegende Funktionen dafür an.