DLL einbinden

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von FloMZ.

    DLL einbinden

    Hallo erstmal in die Runde.

    Ich bin neu hier und habe eine Frage bezüglich der Einbindung einer DLL in ein VB.net Projekt. Ich bin noch sehr neu in der Materie und will mich in die Thematik reinfuchsen. Ich möchte ein Messgerät via USB-Verbindung ansprechen und der Hersteller des Geräts gibt einem hierzu eine DLL an die Hand, und eine C# Datei, die zeigen soll, wie man die Funktionen aus der DLL aufruft.

    Die erste Irritation gab es bei mir, als es nicht funktionierte, über
    Projekt - Verweis hinzufügen - Aktuell - Durchsuchen
    einen Verweis auf die DLL zu legen. Diese ist übrigens im Projektordner abgelegt. Es kommt die Fehlermeldung, dass es fehlgeschlagen ist, und man schauen solle, dass der Zugriff auf die Datei möglich ist, und dass es sich um eine gültige Assembly oder COM Komponente handelt. Stimmt also etwas mit der DLL nicht? Es gibt auch Headerdateien für C++, diesen habe ich bisher noch keine Aufmerksamkeit geschenkt, da diese für C# & VB.NET Programme laut "Dokumentation" nicht benötigt würden...

    Wie gehe ich nun am besten vor, um die DLL doch noch einzubinden? Ich bin für alle Ergebnis-orientierten Ratschläge dankbar :)
    Hallo und willkommen

    Erstmal werden dir sicher mehr Leute helfen können wenn wir mal wissen um was für ein Gerät es sich handelt. Denn meist stehen auf der Herstellerseite Informationen welche DU vieleicht nicht vestehst, andere hier allerdings vieleicht schon. Und schon hat man evtl. eine Lösung.

    Also, was ist das für ein Gerät? Link zur Herstellerseite? Link zum Support mit DLL Download?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @FloMZ Ebenfalls willkommen im Forum. :thumbup:
    Ich arbeite sehr viel mit Third-Party-DLLs und der Hardware dahinter und ich muss sagen, dass ich bisher alle zum Laufen gebracht habe.
    Üblicherweise gibt es zur Hardware x86- und x64-getrennt (mindestens) eine native DLL und eine .NET-Wrapper-DLL dazu.
    Ggf. sind die nativen DLLs auch bei der Software-Installation im Program-Installations-Verzeichnis mit Eintrag in der Systemvariable PSTH.
    Diese .NET-Wrapper-DLL musst Du Deinem Projekt als Verweis hinzufügen.
    Ob die DLL, die Du hast / meinst, eine .NET-DLL ist, weiß ich nicht.
    Poste im Ernstfall die DLL und die C#-Datei (beides in einer ZIP) als Anhang:
    Erweiterte Antwort-> Dateianhänge ->Hochladen.
    ============

    FloMZ schrieb:

    muss man sich anmelden.
    Du hast das Problem, das Du lösen möchtest / musst.
    Ich muss mich nicht anmelden, um Dir zu helfen.
    Natürlich kannst Du die DLL danach ja wieder löschen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @FloMZ Anbei ein kleines Testprojekt mit 3 Aufrufen zur Demonstration.
    Deine DLL muss in das Verzeichnis DLLs, allerdings fehlen da noch weitere DLLs bzw. Treiber, die zum Lieferumfang gehören sollten.
    Dies ist eine native DLL für 32 Bit, die Aufrufe erfolgen so, wie beschrieben, da musst Du auch die Doku intensiv lesen, welche Funktionen mit welchen Parametern aufgerufen werden müssen.
    Dateien
    • DllEinbinden.zip

      (17,05 kB, 181 mal heruntergeladen, zuletzt: )
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So, ein paar Tage sind vergangen. Mittlerweile funktioniert die Verbindung zum Messgerät und Messwerte werden angezeigt. Ich hänge nun ein wenig bei dem Senden von Einstellungen an das Steuergerät. @RodFromGermany hat mir schon sehr weitergeholfen. Bei der "übersetzten" Funktion

    VB.NET-Quellcode

    1. Public Declare Function LS9IF_SetSetting Lib "LS9_IF.dll" (ByVal byDepth As Byte, ByVal stTargetSetting As LS9IF_TARGET_SETTING, ByVal lDataSize As Integer, <[In]()> <Out()> ByVal pbyDatas As Byte(), ByRef pdwError As UInteger) As Integer


    bin ich mir jedoch unsicher. Ich bin bisher noch nicht auf so etwas wie diesen Teil gestoßen:

    VB.NET-Quellcode

    1. <[In]()> <Out()> ByVal pbyDatas As Byte()


    Kann mir vielleicht jemand auf die Sprünge helfen, worum es sich hier handelt, und wie ich die Funktion mit den korrekten Daten füttere? Ich würde mich sehr freuen, gerne auch über Links zu quellen oder ähnlichem.

    Noch eine Info aus dem Handbuch: "pData(in) specifies the buffer in which the setting data to send is stored". Also sozusagen wie ein Zeiger auf den Speicherplatz der Einstellungen die ich senden möchte, korrekt? Warum dann unbedingt ein Byte-Array, wenn ich sowieso immer nur eine Einstellung auf einmal ändern kann?

    Ursprüngliche Form in C#, falls von Interesse:

    C#-Quellcode

    1. [DllImport("LS9_IF.dll")] public static extern int LS9IF_SetSetting(byte byDepth, LS9IF_TARGET_SETTING stTargetSetting, int lDataSize, [In, Out] byte[] pbyDatas, ref uint pdwError);

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „FloMZ“ ()

    FloMZ schrieb:

    <[In]()> <Out()>
    kannst Du für Dich einfach ignorieren.
    Das bedeutet, dass Daten reingehen und Daten rauskommen.
    Du musst dieses Feld wegen ByVal in der richtigen Größe bereitstellen (ansonsten ByRef).
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Danke für die Antwort @RodFromGermany ! :)

    Ok, ich glaube ich brauche noch einen Schubser. Es gibt ein konkretes Beispiel in der Dokumentation der DLL. Könntest du mir sagen, wie ich aus der Tabelle die korrekte Größe, die ich in die oben genannte Funktion als pbyDatas (hier pData genannt) übergeben muss, ermitteln kann und wie ich diese korrekt übergebe? Die Datasize lässt sich ja wohl anhand der Zeilenanzahl in Byte ablesen, wenn ich das richtig verstanden habe.
    Bilder
    • LS9000.jpg

      695,5 kB, 2.016×1.512, 198 mal angesehen
    @FloMZ Lass Dir zunächst von der IDE helfen und schreib den betreffenden Befehl in den Code.
    Was ganz genau bietet er Dir an?
    Klick drauf und drück F12.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @'RodFromGermany : wie meinst du das? Es wird mir momentan kein Fehler angezeigt, nur scheint an meiner Lösung etwas falsch zu sein. Es kommt die Meldung, dass ein invalider Parameter übergeben wurde. Ich habe den Verdacht, dass es an dem pbyDatas liegt. In meinem Fall muss einfach nur eine 1 (für Enable) übertragen und in das 1. von insgesamt 4 Bytes geschrieben werden.

    Eine weitere Fehlerquelle könnte es sein, dass ich die Codes von C# wie folgt übersetzt habe: 0x03 = 3 und 06h = 6 :huh:

    Soweit mein Lösungsansatz:

    VB.NET-Quellcode

    1. Dim TE1 As New Sample.LS9IF_TARGET_SETTING
    2. Dim rc As Integer
    3. Dim byDepth As Byte = Sample.LS9IF_SETTING_DEPTH.LS9IF_SETTING_DEPTH_SAVE
    4. Dim pdwerror As UInteger = 0
    5. Dim Setting As Boolean = 1
    6. TE1.byType = Sample.LS9IF_SETTING_KIND.LS9IF_SETTING_KIND_PROGRAM0 'Programm 0 auswählen
    7. TE1.byCategory = 0 '1. Spalte in der Tabelle
    8. TE1.byItem = 1 '2.Zeile in der Tabelle
    9. TE1.byTarget = 0
    10. TE1.reserve = 4
    11. Dim pbyDatas() As Byte = BitConverter.GetBytes(Setting)
    12. rc = Sample.LS9IF_SetSetting(byDepth, TE1, pbyDatas.Length, pbyDatas, pdwerror)
    13. MsgBox(rc) 'an invalid parameter was passed = 4102​

    FloMZ schrieb:

    Ich habe den Verdacht, dass es an dem pbyDatas liegt.
    Ist ja schon mal ganz gut.
    Klick rechts auf LS9IF_SetSetting, da kommt ein ContextMenu:

    und da lässt Du Dir die Deklaration im ObjectBrowser anzeigen.
    Wenn zur DLL eine entsprechende XML gehört, bekommst Du Hinweise.
    Was steht da?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:


    Was steht da?


    Folgendes habe ich im Objektkatalog zu der Funktion gefunden:

    Public Declare Ansi Function LS9IF_SetSetting Lib "LS9_IF.dll"(byDepth As Byte, stTargetSetting As Test_Keyence_Anzeige.Sample.LS9IF_TARGET_SETTING, lDataSize As Integer, pbyDatas As Byte(), ByRef pdwError As UInteger) As Integer
    Member von "Test_Keyence_Anzeige.Sample.NativeMethods"
    @FloMZ OK,
    Invalid Parameter passt nicht zu einem Byte-Array.
    Möglicherweise ist der Test_Keyence_Anzeige.Sample.LS9IF_TARGET_SETTING-Parameter invalid.
    Was genau ist das?
    Das kriegst Du genau so heraus wie das andere.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:


    Möglicherweise ist der Test_Keyence_Anzeige.Sample.LS9IF_TARGET_SETTING-Parameter invalid.
    Was genau ist das?


    Bei dem Target_Setting Parameter handelt es sich um folgende structure:

    VB.NET-Quellcode

    1. Public Structure LS9IF_TARGET_SETTING
    2. Public byType As Byte
    3. Public byCategory As Byte
    4. Public byItem As Byte
    5. Public reserve As Byte
    6. Public byTarget As Byte
    7. End Structure


    Im Objekt-Browser gibt es keine zusätzlichen Informationen.


    @RodFromGermany: Könnte es daran liegen, dass das Steuergerät die Codes (die Komponenten von der Structure LS9IF_TARGET_SETTING) nicht versteht, weil es sie als Byte geschickt bekommt, und es erwartet Hex-Zahlen? Im ursprünglichen Code (C#) wurden die Codes für die Einstellungen nämlich als Hex übergeben ("0x02", "0x10"...)

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „FloMZ“ ()

    FloMZ schrieb:

    als Hex übergeben ("0x02", "0x10"...)
    Das wäre ein String,
    die Hex-Darstellung eines ganzzahligen Wertes ist lediglich eine seiner möglichen String-Repräsentationen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    FloMZ schrieb:

    Ich habe nun vor die Parameter "&H" gesetzt, womit diese als Hex-Zahl deklariert werden.
    Jou.
    Das ist die VB-Schreibweise für eine Zahl im Hex-Format.
    In C / C++ / C# ist das 0x.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wie ich einen einzelnen Parameter übergebe habe ich nun begriffen. Wie schaut es aber aus, wenn ich mehrere Parameter übergeben muss? Ich möchte nun nicht mehr nur ein Byte mit einer Zahl füllen, sondern die ersten beiden von insgesamt 12 Bytes. Ich nutze wie zuvor den BitConverter.GetBytes, um meine Einstellung (1. Byte = 2, 2.Byte = 0) in ein Byte-Array umzuwandeln. Ich habe eine Lösung gefunden, wie zumindest laut dem Debugger die korrekten Werte in den Bytes stehen, jedoch mag das Steuergerät es so nicht haben. Kennt ihr andere Möglichkeiten das Umzusetzen? Ich habe es gefühlt eher sehr umständlich gemacht ...

    Setting8 ist meine Einstellung, welche ich mit Hilfe des BitConverters umwandeln möchte. Ergebnis soll sein (1. Byte = 2, 2.Byte = 0)

    VB.NET-Quellcode

    1. Dim TE8 As New Sample.LS9IF_TARGET_SETTING
    2. Dim rc8 As Integer
    3. Dim byDepth8 As Byte = Sample.LS9IF_SETTING_DEPTH.LS9IF_SETTING_DEPTH_WRITE
    4. Dim pdwerror8 As UInteger = 0
    5. Dim Setting8 As Int16 = &B0000_0000_0000_0010
    6. TE8.byType = Sample.LS9IF_SETTING_KIND.LS9IF_SETTING_KIND_PROGRAM0 'Programm 0 auswählen
    7. TE8.byCategory = &H3 '4. Spalte in der Tabelle
    8. TE8.byItem = &H1 '2.Zeile in der Tabelle
    9. TE8.byTarget = &H0
    10. TE8.reserve = &HC
    11. Dim pbyDatas8() As Byte = BitConverter.GetBytes(Setting8)
    12. rc8 = Sample.LS9IF_SetSetting(byDepth8, TE8, pbyDatas8.Length, pbyDatas8, pdwerror8)
    13. MsgBox("TE8", ReturnCode(rc8))