NET-Dll in VBA ohne COM-Registrierung nutzen.

    • Allgemein

    Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Mentholi.

      NET-Dll in VBA ohne COM-Registrierung nutzen.

      Jeder der beruflich mit VBA zu tun hat kennt das. Man braucht etwas, aber die benötigte Funktion ist in Excel, Word und Co. nicht enthalten und kann, wenn überhaupt, nur über die Installation von Zusatzsoftware (COM-DLL) oder kompliziert über die Win32API gelöst werden.

      Nun darf man allerdings nicht überall installieren, was man braucht.

      Hier kommt dieses kleine Tutorial ins Spiel.


      Die Vorgabe:
      Zugriff auf eine NET-DLL, ohne etwas zu installieren.

      Lösung:
      Aufrufen der NET-DLL über die COM-Versionen der mscorlib bzw mscoree.

      Zuerst erstellen wir die DLL. Dazu öffnen wir Visual Studio (Express) und legen eine neues DLL-Projekt mit dem Namen "TestDLL" an.

      Wichtig: Das Ganze funktioniert leider nur bis Framework 3.5. Dies muss vor dem Erstellen geändert werden

      Nun zum Code ("Class1.vb"):

      Visual Basic-Quellcode

      1. <System.Runtime.InteropServices.ComVisible(True)> _
      2. Public Class Test
      3. Public Property MYProperty As String = "test"
      4. Public Sub Add(ByVal a As Integer, ByVal b As Integer)
      5. MsgBox(a + b)
      6. End Sub
      7. End Class


      Der einzige Unterschied zu einer normalen DLL, ist die Verwendung von

      Visual Basic-Quellcode

      1. <System.Runtime.InteropServices.ComVisible(True)> _

      um dem Compiler zu sagen, dass die gesamte Klasse für COM-Clients sichtbar ist.

      Nun zu VBA.

      In VBA müssen zwei Verweise hinzugefügt werden:
      C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb (Common Language Runtime Execution Engine 2.4 Library)
      C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb

      Danach kann man mit folgendem Code die Funktionen der DLL aufrufen.

      Visual Basic-Quellcode

      1. Sub DLLTest()
      2. 'Wird benötigt, um Funktionen mit der CLR auszuführen
      3. Dim clr As mscoree.CorRuntimeHost
      4. 'Stellt die Funktionalität zum Laden der DLL bereit
      5. Dim domain As mscorlib.AppDomain
      6. 'Hier wird die Instanz der Klasse "TestDLL.Test" gespeichert
      7. Dim objTest As Object
      8. 'Erzeugt einen neuen RuntimeHost
      9. Set clr = New mscoree.CorRuntimeHost
      10. 'Starten des RuntimeHosts
      11. clr.Start
      12. 'Die Standard AppDomain holen
      13. clr.GetDefaultDomain domain
      14. 'Hier wird eine Instanz der Klasse "TestDLL.Test" erstellt
      15. 'Pfad_Zur_Dll muss mit dem Pfad ersetzt werden, auf dem die DLL liegt. Kann auch ein UNC-Pfad sein.
      16. Set objTest = domain.CreateInstanceFrom("Pfad_Zur_Dll\TestDLL.dll", "TestDLL.Test").Unwrap
      17. 'Hier wird das Ganze getestet
      18. MsgBox objTest.MYProperty
      19. objTest.MYProperty = "Franz"
      20. Call objTest.Add(14, 6)
      21. MsgBox objTest.MYProperty
      22. 'Referenz löschen
      23. Set objTest = Nothing
      24. 'RuntimeHost stoppen
      25. clr.Stop
      26. End Sub


      Nun kann man auf (fast) alle Funktionen der DLL zugreifen.

      Vorteil dieser Methode:
      Keine Installation

      Nachteile dieser Methode:
      Keine IntelliSens in VBA

      Allgemein gilt, wie bei normalen COM-DLLs, gewisse Dinge können nicht an VBA übergeben werden. Dafür kann man sich allerdings meistens einen Workaround basteln.
      SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

      Weil einfach, einfach zu einfach ist! :D
      Habe das alles so nachvollzogen.
      An was könnte es denn liegen, dass ich bei Ablauf in VBA beim Set objTest = domain.CreateInstanceFrom("D:\TestDLL.dll", "TestDLL.dll").Unwrap die Fehlermeldung
      "Der Typ TestDLL.DLL in der Assembly TestDLL, Version ....PublicKeyToken=Null konnte nicht geladen werden"
      ???
      Vermutlich hast du keine Klasse namens DLL in Namespace deiner TestDLL.
      domain.CreateInstanceFrom("D:\TestDLL.dll", "TestDLL.dll")

      Der Typ TestDLL.DLL konnte nicht geladen werden. Der 2. Parameter gibt den Typ an, von dem du eine Instanz haben willst.
      Hast du in der TestDLL.DLL also eine KLasse MyClass dann wäre der Aufruf:
      domain.CreateInstanceFrom("D:\TestDLL.dll", "TestDLL.MyClass ")
      Das ist meine Signatur und sie wird wunderbar sein!