Exemplarische Vorgehensweise: Aufrufen von Windows-APIs (Visual Basic)
Windows-APIs sind DLLs (Dynamic Link Libraries), die Teil des Windows-Betriebssystems sind. Sie werden verwendet, um Aufgaben auszuführen, wenn es schwierig ist, eigene gleichwertige Prozeduren zu schreiben. Windows bietet beispielsweise eine Funktion namens FlashWindowEx
, mit der Sie die Titelleiste einer Anwendung abwechselnd hell und dunkel schattieren können.
Der Vorteil der Verwendung von Windows-APIs in Ihrem Code besteht darin, dass sie Entwicklungszeit einsparen können, da sie Dutzende von nützlichen Funktionen enthalten, die bereits geschrieben wurden und darauf warten, verwendet zu werden. Der Nachteil besteht darin, dass die Windows-APIs schwer zu handhaben sind und bei Problemen keine Nachsicht walten lassen.
Windows-APIs stellen eine besondere Kategorie von Interoperabilität dar. Windows-APIs verwenden keinen verwalteten Code, verfügen nicht über integrierte Typbibliotheken und verwenden Datentypen, die sich von denen unterscheiden, die mit Visual Studio verwendet werden. Aufgrund dieser Unterschiede und weil es sich bei Windows-APIs nicht um COM-Objekte handelt, wird Interoperabilität mit Windows-APIs und .NET Framework mit einem Plattformaufruf oder PInvoke durchgeführt. Der Plattformaufruf ist ein Dienst, der es verwaltetem Code ermöglicht, nicht verwaltete Funktionen aufzurufen, die in DLLs (Dynamic Link Library) implementiert sind. Weitere Informationen finden Sie unter Verwenden nicht verwalteter DLL-Funktionen. Sie können PInvoke in Visual Basic verwenden, indem Sie entweder die Declare
-Anweisung verwenden oder das DllImport
-Attribut auf eine leere Prozedur anwenden.
Windows-API-Aufrufe waren in der Vergangenheit ein wichtiger Bestandteil der Visual Basic-Programmierung, sind aber mit Visual Basic .NET nur selten erforderlich. Wenn möglich, sollten Sie verwalteten Code aus .NET Framework anstelle von Windows-API-Aufrufen verwenden, um Aufgaben auszuführen. Diese exemplarische Vorgehensweise enthält Informationen zu Situationen, in denen die Verwendung von Windows-APIs erforderlich ist.
Hinweis
Auf Ihrem Computer werden möglicherweise andere Namen oder Speicherorte für die Benutzeroberflächenelemente von Visual Studio angezeigt als die in den folgenden Anweisungen aufgeführten. Diese Elemente sind von der jeweiligen Visual Studio-Version und den verwendeten Einstellungen abhängig. Weitere Informationen finden Sie unter Personalisieren der IDE.
API-Aufrufe mithilfe von Declare
Die gängigste Methode zum Aufrufen von Windows-APIs ist die Verwendung der Declare
-Anweisung.
So deklarieren Sie eine DLL-Prozedur
Bestimmen Sie den Namen der Funktion, die Sie aufrufen möchten, sowie deren Argumente, Argumenttypen und Rückgabewert sowie den Namen und Speicherort der DLL, die sie enthält.
Hinweis
Vollständige Informationen zu den Windows-APIs finden Sie in der Win32 SDK-Dokumentation in der Windows-API des Platform SDK. Weitere Informationen zu den Konstanten, die von Windows-APIs verwendet werden, finden Sie in den Headerdateien wie „Windows.h“, die im Platform SDK enthalten sind.
Öffnen Sie ein neues Windows-Anwendungsprojekt, indem Sie im Menü Datei auf Neu und dann auf Projekt klicken. Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie in der Liste der Visual Basic-Projektvorlagen die Option Windows-Anwendung aus. Das neue Projekt wird angezeigt.
Fügen Sie die folgende
Declare
-Funktion entweder der Klasse oder dem Modul hinzu, in der bzw. dem Sie die DLL verwenden möchten:Declare Auto Function MBox Lib "user32.dll" Alias "MessageBox" ( ByVal hWnd As Integer, ByVal txt As String, ByVal caption As String, ByVal Typ As Integer) As Integer
Teile der Declare-Anweisung
Die Declare
-Anweisung schließt die folgenden Elemente ein.
Automatischer Modifizierer
Der Auto
-Modifizierer weist die Laufzeit an, die Zeichenfolge basierend auf dem Methodennamen gemäß Common Language Runtime-Regeln (oder dem Aliasnamen, falls angegeben) zu konvertieren.
Bibliotheks- und Aliasschlüsselwörter
Der Name, der auf das Function
-Schlüsselwort folgt, ist der Name, den Ihr Programm für den Zugriff auf die importierte Funktion verwendet. Er kann mit dem tatsächlichen Namen der Funktion identisch sein, die Sie aufrufen, oder Sie können einen beliebigen gültigen Prozedurnamen verwenden und dann das Alias
-Schlüsselwort verwenden, um den tatsächlichen Namen der Funktion anzugeben, die Sie aufrufen.
Geben Sie das Lib
-Schlüsselwort an, gefolgt vom Namen und Speicherort der DLL, die die Funktion enthält, die Sie aufrufen. Sie müssen den Pfad für Dateien in den Windows-Systemverzeichnissen nicht angeben.
Verwenden Sie das Alias
-Schlüsselwort, wenn der Name der aufgerufenen Funktion kein gültiger Visual Basic-Prozedurname ist oder mit dem Namen anderer Elemente in Ihrer Anwendung in Konflikt steht. Alias
gibt den tatsächlichen Namen der aufgerufenen Funktion an.
Argument- und Datentypdeklarationen
Deklarieren Sie die Argumente und ihre Datentypen. Dieser Aspekt kann eine Herausforderung darstellen, da die von Windows verwendeten Datentypen nicht den Visual Studio-Datentypen entsprechen. Visual Basic erledigt einen Großteil dieser Aufgabe für Sie, indem Argumente in kompatible Datentypen konvertiert werden – ein Prozess, der als Marshalling bezeichnet wird. Sie können mithilfe des im System.Runtime.InteropServices-Namespace definierten MarshalAsAttribute-Attributs explizit steuern, wie Argumente gemarshallt werden.
Hinweis
In früheren Versionen von Visual Basic konnten Sie As Any
-Parameter deklarieren, was bedeutet, dass Daten eines beliebigen Datentyps verwendet werden konnten. Visual Basic erfordert, dass Sie einen bestimmten Datentyp für alle Declare
-Anweisungen verwenden.
Windows-API-Konstanten
Einige Argumente sind Kombinationen von Konstanten. Die in dieser exemplarischen Vorgehensweise gezeigte MessageBox
-API akzeptiert beispielsweise ein ganzzahliges Argument namens Typ
, das steuert, wie das Meldungsfeld angezeigt wird. Sie können den numerischen Wert dieser Konstanten ermitteln, indem Sie die #define
-Anweisungen in der Datei „WinUser.h“ untersuchen. Die numerischen Werte werden im Allgemeinen im Hexadezimalformat angezeigt. Daher können Sie einen Rechner verwenden, um sie hinzuzufügen und in Dezimalwerte zu konvertieren. Wenn Sie z. B. die Konstanten für das Ausrufezeichen MB_ICONEXCLAMATION
0x00000030 und das Ja/Nein-Format MB_YESNO
0x00000004 kombinieren möchten, können Sie die Zahlen addieren und ein Ergebnis von 0x00000034 oder 52 (Dezimalwert) erhalten. Auch wenn Sie das Dezimalergebnis direkt verwenden können, ist es besser, diese Werte in Ihrer Anwendung als Konstanten zu deklarieren und dann mit dem Or
-Operator zu kombinieren.
So deklarieren Sie Konstanten für Windows-API-Aufrufe
Ziehen Sie die Dokumentation für die Windows-Funktion zu Rate, die Sie aufrufen. Bestimmen Sie den Namen der verwendeten Konstanten und den Namen der H-Datei, die die numerischen Werte für diese Konstanten enthält.
Verwenden Sie einen Text-Editor, z. B. Editor, um den Inhalt der Headerdatei (H-Datei) anzuzeigen und die Werte zu ermitteln, die den von Ihnen verwendeten Konstanten zugeordnet sind. Beispielsweise verwendet die
MessageBox
-API die KonstanteMB_ICONQUESTION
, um ein Fragezeichen im Meldungsfeld anzuzeigen. Die Definition fürMB_ICONQUESTION
befindet sich in „WinUser.h“ und sieht wie folgt aus:#define MB_ICONQUESTION 0x00000020L
Fügen Sie Ihrer Klasse oder Ihrem Modul entsprechende
Const
-Anweisungen hinzu, um diese Konstanten für Ihre Anwendung verfügbar zu machen. Zum Beispiel:Const MB_ICONQUESTION As Integer = &H20 Const MB_YESNO As Integer = &H4 Const IDYES As Integer = 6 Const IDNO As Integer = 7
So rufen Sie die DLL-Prozedur auf
Fügen Sie dem Startformular für Ihr Projekt eine Schaltfläche mit dem Namen
Button1
hinzu, und doppelklicken Sie dann darauf, um den zugehörigen Code anzuzeigen. Der Ereignishandler für die Schaltfläche wird angezeigt.Fügen Sie dem
Click
-Ereignishandler Code für die Schaltfläche hinzu, die Sie hinzugefügt haben, um die Prozedur aufzurufen und die entsprechenden Argumente anzugeben:Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' Stores the return value. Dim RetVal As Integer RetVal = MBox(0, "Declare DLL Test", "Windows API MessageBox", MB_ICONQUESTION Or MB_YESNO) ' Check the return value. If RetVal = IDYES Then MsgBox("You chose Yes") Else MsgBox("You chose No") End If End Sub
Führen Sie das Projekt aus, indem Sie F5 drücken. Das Meldungsfeld wird mit den Antwortschaltflächen Ja und Nein angezeigt. Klicken Sie auf eine der beiden Optionen.
Marshallen von Daten
Visual Basic konvertiert automatisch die Datentypen von Parametern und Rückgabewerten für Windows-API-Aufrufe. Sie können jedoch das MarshalAs
-Attribut verwenden, um nicht verwaltete Datentypen explizit anzugeben, die von einer API erwartet werden. Weitere Informationen zum Interop-Marshalling finden Sie unter Interop-Marshalling.
So verwenden Sie Declare und MarshalAs in einem API-Aufruf
Bestimmen Sie den Namen der Funktion, die Sie aufrufen möchten, sowie deren Argumente, Datentypen und den Rückgabewert.
Um den Zugriff auf das
MarshalAs
-Attribut zu vereinfachen, fügen Sie eineImports
-Anweisung am Anfang des Codes für die Klasse oder das Modul hinzu, wie im folgenden Beispiel gezeigt:Imports System.Runtime.InteropServices
Fügen Sie der verwendeten Klasse oder dem verwendeten Modul einen Funktionsprototyp für die importierte Funktion hinzu, und wenden Sie das
MarshalAs
-Attribut auf die Parameter oder den Rückgabewert an. Im folgenden Beispiel wird ein API-Aufruf, der den Typvoid*
erwartet, alsAsAny
gemarshallt:Declare Sub SetData Lib "..\LIB\UnmgdLib.dll" ( ByVal x As Short, <MarshalAsAttribute(UnmanagedType.AsAny)> ByVal o As Object)
API-Aufrufe mithilfe von DllImport
Das DllImport
-Attribut bietet eine zweite Möglichkeit zum Aufrufen von Funktionen in DLLs ohne Typbibliotheken. DllImport
entspricht ungefähr der Verwendung einer Declare
-Anweisung, bietet aber größere Kontrolle darüber, wie Funktionen aufgerufen werden.
Sie können DllImport
mit den meisten Windows-API-Aufrufen verwenden, solange sich der Aufruf auf eine freigegebene (manchmal als statisch bezeichnete) Methode bezieht. Sie können keine Methoden verwenden, die eine Instanz einer Klasse erfordern. Im Gegensatz zu Declare
-Anweisungen können DllImport
-Aufrufe das MarshalAs
-Attribut nicht verwenden.
So rufen Sie eine Windows-API mithilfe des DllImport-Attributs auf
Öffnen Sie ein neues Windows-Anwendungsprojekt, indem Sie im Menü Datei auf Neu und dann auf Projekt klicken. Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie in der Liste der Visual Basic-Projektvorlagen die Option Windows-Anwendung aus. Das neue Projekt wird angezeigt.
Fügen Sie dem Startformular eine Schaltfläche mit dem Namen
Button2
hinzu.Doppelklicken Sie auf
Button2
, um die Codeansicht für das Formular zu öffnen.Um den Zugriff auf
DllImport
zu vereinfachen, fügen Sie am Anfang des Codes für die Startformularklasse eineImports
-Anweisung hinzu:Imports System.Runtime.InteropServices
Deklarieren Sie eine leere Funktion vor der
End Class
-Anweisung für das Formular, und nennen Sie die FunktionMoveFile
.Wenden Sie die
Public
- undShared
-Modifizierer auf die Funktionsdeklaration an, und legen Sie Parameter fürMoveFile
basierend auf den Argumenten fest, die von der Windows-API-Funktion verwendet werden:Public Shared Function MoveFile( ByVal src As String, ByVal dst As String) As Boolean ' Leave the body of the function empty. End Function
Ihre Funktion kann einen beliebigen gültigen Prozedurnamen aufweisen. das
DllImport
-Attribut gibt den Namen in der DLL an. Außerdem wird das Marshalling der Interoperabilität für die Parameter und Rückgabewerte verarbeitet, sodass Sie Visual Studio-Datentypen auswählen können, die den Datentypen ähneln, die von der API verwendet werden.Wenden Sie das
DllImport
-Attribut auf die leere Funktion an. Der erste Parameter ist der Name und der Speicherort der DLL, die die Funktion enthält, die Sie aufrufen. Sie müssen den Pfad für Dateien in den Windows-Systemverzeichnissen nicht angeben. Der zweite Parameter ist ein benanntes Argument, das den Namen der Funktion in der Windows-API angibt. In diesem Beispiel erzwingt dasDllImport
-Attribut, dass Aufrufe vonMoveFile
anMoveFileW
in „KERNEL32.DLL“ weitergeleitet werden. DieMoveFileW
-Methode kopiert eine Datei aus dem Pfadsrc
in den Pfaddst
.<DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Public Shared Function MoveFile( ByVal src As String, ByVal dst As String) As Boolean ' Leave the body of the function empty. End Function
Fügen Sie dem
Button2_Click
-Ereignishandler Code hinzu, um die Funktion aufzurufen:Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim RetVal As Boolean = MoveFile("c:\tmp\Test.txt", "c:\Test.txt") If RetVal = True Then MsgBox("The file was moved successfully.") Else MsgBox("The file could not be moved.") End If End Sub
Erstellen Sie eine Datei mit dem Namen „Test.txt“, und platzieren Sie sie im Verzeichnis „C:\Tmp“ auf Ihrer Festplatte. Erstellen Sie bei Bedarf das Verzeichnis „Tmp“.
Drücken Sie F5, um die Anwendung zu starten. Das Hauptformular wird angezeigt.
Klicken Sie auf Button2. Die Meldung „The file was moved successfully“ (Die Datei wurde erfolgreich verschoben) wird angezeigt, wenn die Datei verschoben werden kann.