dll verwenden

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Mad Andy.

    dll verwenden

    Hi!

    ich hab jetzt schon ne Zeit gegooglet un die MSDN gequält, aber da kam irgendwie nichts gescheites raus...

    Also: Ich würd gerne so ne Art Add-On-System machen, und mir schon überlegt, dass ich das mit Klassenbibliotheken machen will. Aber wie schaff ich es, eine dll flexibel einzubinden? also dass ich den Dateinamen weiß, un dann ne bestimmte Funkion aufrufen kann? Hoffe da kann mir einer helfen...

    vG,
    Lupus
    Hallo Lupus !

    Das ist doch gar kein Problem, öffne Neue Klassen Bibliotek und schreibe alle Funkrionen die du haben willst, nach dem du das vertig geschrieben hast, kannst in Fom Code ein Veweis auf dein DLL erstellen.
    Dann kannst deine Funktionen aufrufen.
    Nur als Beispil:

    1 Das schreibst du in Klassen bibliotek:

    VB.NET-Quellcode

    1. 'VERGBIST DEINE SPACE NAME "RECHNEN"
    2. Public Function Rechnen ( Zahl1 As Long, Zahl2, As Long ) As Long
    3. Rechnen = Zahl1 +Zahl2
    4. End Function



    2 Speichern unter Rechen.dll
    3. In Form Code erstellest du verweis auf Rechen.dll
    4. Jetzt die Funktion aufrufen:

    VB.NET-Quellcode

    1. Imports Rechnen
    2. ' Varibale deklariren
    3. Private Z1 As Integer
    4. Private Z2 Integer
    5. Private Ergebnis As Integer
    6. Private ff As Rechen
    7. 'Die Code schreibst du in irgend einen Erreignis rein
    8. ff = New Rechen
    9. Z1 =100
    10. Z2 = 200
    11. Ergebnis = ff (Z1, Z2) 'hier wird die Funktion aus DLL aufgerufen




    Mfg Alex :thumbup: :thumbup: ;)
    soweit war ich auch schon... aber vielleicht hast du bemerkt, dass ich das flexibel machen will, also wenn das Programm schon kompiliert is un die Datei erst später bekannt wird! Trotzdem danke für den Versuch ^^
    Hi!

    Es gibt 2 Möglichkeiten:
    • Falls du .net 3.5 verwendest (was eigentlich noch immer zu neu ist), gibt's da ein neues Pluginsystem. Eine kurze Grafik dazu findest du hier. Der Namespace, den du dir dazu anschauen solltest heißt System.Plugin.
    • Man kann DLLs zur Laufzeit laden und Funktionen per String ausführen. Einziges Problem ist, dass du vorher (z.B. per Interface oder Vererbung) festlegen musst, welche Properties und Funktionen die Klasse/DLL haben muss. Bei einer Funktion mit unbestimmten Parametern kannst du mit Collections (Arraylist, Hashtable) arbeiten.
      Ich hoffe du verstehst C#, das hat bei komplexen Dingen scheinbar eine viel größere Community. Das hier hab ich z.B. zu dem Thema gefunden.
      Beim Classname musst du, so weit ich weiß, den Namespace auch davor schreiben. Bei nicht-shared Methoden (shared heißt in C# static), kommen Interfaces und Vererbung zu gute, falls das überhaupt möglich ist (habs noch nie Versucht).

    mfG
    Andy

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Mad Andy“ ()

    hallo lupus,

    wie mad andy schon richtig erwähnt hat, musst du zumindest unter framework 2 eine schnittstelle schaffen.
    diese schnittstellen, muss deine dll implementieren.

    deine host anwendung prüft dann die entsprechenden dll's ab, ob diese kompatibel sind und bindet sie ggf. ein.

    EDIT:
    ich hab mal ein kleines beispiel projekt erstellt.
    leider kann ich es vom hotel hier nicht auf meine hp laden. wenn du es haben willst schick ich es dir gerne.
    vielleicht schreib ich heute mal ein kleines tutorial, wie man sowas angeht - aber jetzt schau ich mir mal ein bischen die downtown von shanghai an. :D

    gruss

    mikeb69

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mikeb69“ ()

    Hi!

    danke für die Informationen, ich schaus mir mal an.
    Den Synax von C kenn ich, also ich könnt zurechtkommen ^^

    vG,
    Lupus

    Edit:
    hab jetzt den Link ma unter die Lupe genommen un das rausbekommen:

    Dll:

    VB.NET-Quellcode

    1. Public Class class1
    2. Sub Test(ByVal text As String)
    3. MsgBox(text)
    4. End Sub
    5. End Class


    Aufruf:

    VB.NET-Quellcode

    1. Imports System.Reflection
    2. Public Class Form1
    3. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    4. LoadDllMethod("testdll.class1", "Test", Pfad & "addons\testdll.dll", New Object() {})
    5. Ordner.Checked = Not SplitC.Panel1Collapsed
    6. End Sub
    7. Public Function LoadDllMethod(ByVal title_class As String, ByVal title_void As String, ByVal path As String, ByVal parameters As Object()) As String
    8. Dim u As Assembly = Assembly.LoadFile(path)
    9. Dim t As Type = u.GetType(title_class)
    10. If Not t Is Nothing Then
    11. Dim m As MethodInfo = t.GetMethod(title_void)
    12. If Not m Is Nothing Then
    13. If parameters.Length >= 1 Then
    14. Dim myparam(1)() As Object
    15. myparam(0) = parameters
    16. Return m.Invoke(Nothing, myparam)
    17. Else
    18. Return m.Invoke(Nothing, Nothing)
    19. End If
    20. End If
    21. End If
    22. Throw New Exception("method/class not found")
    23. End Function
    24. End Class

    da gibts dann bei "m.Invoke(Nothing, Nothing)" (einer der letzten Zeilen) ne Fehlermeldung:
    "Die nicht-statische Methode erfordert ein Ziel."

    Weiß einer was man da machen kann?

    vG,
    Lupus

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Lupus“ ()

    Hi!

    Wenn du keine statischen (in VB shared) Methoden / Klassen verwendest, muss der erste Parameter eine Instanz der Klasse (class1) sein!
    Entweder deklarierst du die Methode und/oder die Klasse als shared (Programm bleibt gleich):

    VB.NET-Quellcode

    1. Public Shared Class class1
    2. ' man sollte übrigens Public Subs als Public deklarieren und den Zugriffsmodifikator nicht einfach weglassen ;)
    3. Public Shared Sub Test(ByVal Text As String)
    4. MsgBox(Text)
    5. End Sub
    6. End Class


    Oder du erstellst vorher eine Instanz (Klasse bleibt gleich):

    VB.NET-Quellcode

    1. Public Function LoadDllMethod(ByVal title_class As String, ByVal title_void As String, ByVal path As String, ByVal parameters As Object()) As String
    2. Dim u As Assembly = Assembly.LoadFile(path)
    3. Dim t As Type = u.GetType(title_class)
    4. If Not t Is Nothing Then
    5. Dim m As MethodInfo = t.GetMethod(title_void)
    6. Dim myInstance As Object = u.CreateInstance(t.FullName) ' neu
    7. If (Not m Is Nothing) and (Not myInstance Is Nothing) Then ' geändert
    8. If parameters.Length >= 1 Then
    9. Dim myparam(1)() As Object
    10. myparam(0) = parameters
    11. Return m.Invoke(myInstance, myparam) ' geändert
    12. Else
    13. Return m.Invoke(myInstance, Nothing) ' geändert
    14. End If
    15. End If
    16. End If
    17. Throw New Exception("method/class not found")
    18. End Function


    • Überall, wo Klassen / Member-Methods sinnlos sind, solltest du auf static / shared Methoden zurückgreifen (z.B. Funktionen, die unabhängig sind).
    • Die 1-Buchstaben-Variablen sind meistens verwirrend, anständige Namen sind besser.
    • Der Rückgabewert einer allgemeinen LoadDLLMethod-Funktion sollte Object sein, dann kannst du später im Programm entscheiden, was es ist und das Casten bzw. von VB Casten lassen.

      VB.NET-Quellcode

      1. ' Hier muss dann weniger sinnlos herumgecastet werden
      2. ' bzw. String->Integer ist immer Böse ^^:
      3. Dim x as Int = LoadDLLMethod(...)
      4. Dim s as String = LoadDLLMethod(...)
      5. Dim d as Double = LoadDLLMethod(...)

    • Wenn du Konstruktoren mit Parametern hast und/oder überladene Funktionen, kannst du in der MSDN die ganzen Klassenbeschreibungen und Methodenbeschreibungen von Überladungen lesen. Bei der MSDN ist Englisch sehr ratsam, da viele Sachen wirklich schlecht übersetzt sind!

    so long..
    Andy
    yeah danke Mad Andy!! Du hast mir sehr geholfen!

    Musste noch nen mir sowieso unlogisch erscheinenden Teil ändern:

    VB.NET-Quellcode

    1. If parameters.Length >= 1 Then
    2. Return m.Invoke(myInstance, parameters) ' geändert
    3. Else


    endlich kann ich weitermachen :)
    So genau hab ich mir das garnicht angeschaut :D
    Einfach Copy&Paste und meinen Senf dazu ^^

    Edit: muss noch was dazu sagen. Wenn du das ganze mit Klassen machst (Objekt-Variable / Erster Parameter bei Invoke), würd ich die Instanz nicht einfach jedes mal wegschmeißen und neu erstellen, sondern irgendwo als Parameter einbauen (ByRef oder eine getrennte Funktion zum Instanziieren machen).
    Hi!

    Der Sinn von Klassen ist, dass du Funktionen mit gespeicherten Werten verbindest. Für einfache Filterfunktionen, die auf keine gespeicherten Werte zurückgreifen, nimmt man Shared Subs. Bei kompliziertere Sachen, wo man eine lang-dauernde Initialisierung braucht oder es ne Menge Parameter gibt, die man nicht in einen Funktionsaufruf packen will, will man die bisherigen Werte nicht einfach verwefen -> man nimmt Klassen. Die Instanz dann wieder wegzuschmeißen heißt, dass du die langwirrige Initialisierung (falls es eine gibt) neu durchgehen musst und die Parameter nicht speichern kanst, in dem Fall kannste gleich eine Shared Sub verwenden.