Exemplarische Vorgehensweise: Aufrufen von Windows-APIs
Aktualisiert: November 2007
Windows-APIs sind DLLs (Dynamic Link Libraries), die Bestandteil des Betriebssystems Windows sind. Verwenden Sie DLLs, wenn das Schreiben eigener Prozeduren für bestimmte Aufgaben zu aufwendig ist. Windows bietet z. B. die Funktion FlashWindowEx, mit der Sie die Farbe einer Titelleiste für eine Anwendung von Hell nach Dunkel wechseln lassen können.
Der Vorteil der Verwendung von Windows-APIs im Code ist die verkürzte Entwicklungszeit, da Sie Dutzende hilfreiche und bereits verfasste Funktionen verwenden können. Ein Nachteil von Windows-APIs ist, dass die Verwendung möglicherweise schwierig ist und Probleme kaum abgefangen werden können.
Windows-APIs stellen eine besondere Kategorie der Interoperabilität dar. Windows-APIs verwenden keinen verwalteten Code, verfügen nicht über integrierte Typbibliotheken und verwenden andere Datentypen als Visual Studio. Aufgrund dieser Unterschiede und weil Windows-APIs keine COM-Objekte sind, erfolgt die Zusammenarbeit zwischen Windows-APIs und .NET Framework über die Plattformaktivierung (PInvoke). Die Plattformaktivierung ist ein Dienst, mit dem verwalteter Code nicht verwaltete Funktionen aufrufen kann, die in DLLs implementiert sind. Weitere Informationen hierzu finden Sie unter Verwenden nicht verwalteter DLL-Funktionen. Sie können PInvoke in Visual Basic entweder durch Verwendung der Declare-Anweisung oder durch Anwenden des DllImport-Attributs auf eine leere Prozedur verwenden.
Windows-API-Aufrufe waren in der Vergangenheit ein wichtiger Bestandteil der Visual Basic-Programmierung, sind aber bei Visual Basic 2005 selten erforderlich. Verwenden Sie zum Ausführen von Aufgaben nach Möglichkeit immer verwalteten Code von .NET Framework anstelle von Windows-API-Aufrufen. Diese exemplarische Vorgehensweise enthält Informationen über die Situationen, in denen die Verwendung von Windows-APIs erforderlich ist.
Hinweis: |
---|
Je nach den aktiven Einstellungen oder der verwendeten Version, können sich die angezeigten Dialogfelder und Menübefehle von den in der Hilfe beschriebenen unterscheiden. Klicken Sie im Menü Extras auf Einstellungen importieren und exportieren, um die Einstellungen zu ändern. Weitere Informationen hierzu finden Sie unter Visual Studio-Einstellungen. |
API-Aufrufe mit "Declare"
Aufrufe von Windows-APIs erfolgen im Allgemeinen über die Declare-Anweisung.
So deklarieren Sie eine DLL-Prozedur
Bestimmen Sie den Namen der aufzurufenden Funktion und der Argumente, Argumenttypen und Rückgabewerte sowie den Namen und Speicherort der DLL, die die Funktion enthält.
Hinweis: Vollständige Informationen über Windows-APIs finden Sie in der Win32-SDK-Dokumentation im Platform SDK Windows-API. Weitere Informationen über die von Windows-APIs verwendeten Konstanten finden Sie im Platform SDK in Headerdateien wie Windows.h.
Öffnen Sie ein neues Windows-Anwendungsprojekt, indem Sie im Menü Datei erst auf Neu und dann auf Projekt klicken. Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie in der Liste der Visual Basic-Projektvorlagen 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
Bestandteile der Declare-Anweisung
Die Declare-Anweisung enthält folgende Elemente:
Auto-Modifizierer
Der Auto-Modifizierer weist die Common Language Runtime an, die Zeichenfolge entsprechend dem Methodennamen (oder Aliasnamen, sofern angegeben) nach den Regeln der Common Language Runtime zu konvertieren.
Schlüsselwörter "Lib" und "Alias"
Anhand des Namens, der auf das Schlüsselwort Function folgt, greift das Programm auf die importierte Funktion zu. Dieser kann mit dem eigentlichen Namen der aufgerufenen Funktion übereinstimmen. Sie können aber einen beliebigen gültigen Prozedurnamen verwenden und anschließend mit dem Schlüsselwort Alias den eigentlichen Namen der aufgerufenen Funktionen angeben.
Geben Sie das Lib-Schlüsselwort an, gefolgt von dem Namen und Speicherort der DLL mit der aufgerufenen Funktion. Sie brauchen den Pfad zu Dateien in Windows-Systemverzeichnissen nicht anzugeben.
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 der Anwendung in Konflikt steht. Alias gibt den eigentlichen Namen der aufgerufenen Funktion an.
Argument- und Datentypdeklarationen
Deklarieren Sie die Argumente und deren Datentypen. Dieser Teil kann problematisch sein, weil die von Windows verwendeten Datentypen nicht den Visual Studio-Datentypen entsprechen. Visual Basic nimmt Ihnen sehr viel Arbeit ab, indem es die Argumente in kompatible Datentypen konvertiert. Dieser Prozess wird als Marshalling bezeichnet. Sie können das Marshalling der Argumente explizit steuern, indem Sie das im System.Runtime.InteropServices-Namespace definierte MarshalAsAttribute-Attribut verwenden.
Hinweis: |
---|
Bei älteren Versionen von Visual Basic konnten Sie Parameter als As Any deklarieren, d. h., dass Daten eines beliebigen Datentyps verwendet werden konnten. Bei Visual Basic müssen 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 übernimmt z. B. das integer-Argument Typ, das die Anzeige des Meldungsfelds steuert. Sie können den numerischen Wert dieser Konstanten feststellen, indem Sie die #define-Anweisungen in der Datei WinUser.h überprüfen. Die numerischen Werte werden im Allgemeinen hexadezimal angezeigt. Verwenden Sie einen Taschenrechner, um sie zu addieren und in Dezimalwerte zu konvertieren. Wenn Sie z. B. die Konstanten für das Format mit Ausrufezeichen MB_ICONEXCLAMATION 0x00000030 und das Format mit Ja/Nein-Schaltflächen MB_YESNO 0x00000004 kombinieren möchten, können Sie die Zahlen addieren, und erhalten so als Ergebnis 0x00000034 bzw. im Dezimalformat 52. Sie können das Dezimalergebnis direkt verwenden, es wird aber empfohlen, diese Werte als Konstanten in der Anwendung zu deklarieren und mit dem Or-Operator zu kombinieren.
So deklarieren Sie Konstanten für Windows-API-Aufrufe
Schlagen Sie in der Dokumentation für die aufgerufene Windows-Funktion nach. Bestimmen Sie den Namen der verwendeten Konstanten und den Namen der H-Datei, die die numerischen Werte für diese Konstanten enthält.
Öffnen Sie die Headerdatei (H-Datei) in einem Text-Editor (z. B. Windows Editor), und suchen Sie die den verwendeten Konstanten zugeordneten Werte. Die MessageBox-API verwendet z. B. die MB_ICONQUESTION-Konstante zum Anzeigen eines Fragezeichens im Meldungsfeld. Die Definition für MB_ICONQUESTION steht in WinUser.h und lautet folgendermaßen:
#define MB_ICONQUESTION 0x00000020L
Fügen Sie der Klasse oder dem Modul entsprechende Const-Anweisungen hinzu, um diese Konstanten in der Anwendung verfügbar zu machen. 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 des Projekts die Schaltfläche Button1 hinzu, und doppelklicken Sie anschließend darauf, um ihren Code anzuzeigen. Der Ereignishandler für die Schaltfläche wird angezeigt.
Fügen Sie im Click-Ereignishandler Code für die Schaltfläche hinzu, die Sie für den Aufruf der Prozedur hinzugefügt haben, und geben Sie die entsprechenden Argumente an:
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 Schaltflächen.
Datenmarshalling
Visual Basic konvertiert die Datentypen von Parametern und Rückgabewerten für Windows-API-Aufrufe automatisch. Sie können aber mit dem MarshalAs-Attribut explizit nicht verwaltete Datentypen angeben, die von einer API erwartet werden. Weitere Informationen über das Interop-Marshalling finden Sie unter Interop-Marshalling.
So verwenden Sie "Declare" und "MarshalAs" in einem API-Aufruf
Bestimmen Sie den Namen der aufzurufenden Funktion sowie deren Argumente, Datentypen und Rückgabewerte.
Um den Zugriff auf das MarshalAs-Attribut zu vereinfachen, fügen Sie am Anfang des Codes für die Klasse oder das Modul wie im folgenden Beispiel gezeigt eine Imports-Anweisung ein:
Imports System.Runtime.InteropServices
Fügen Sie in der verwendeten Klasse oder im verwendeten Modul einen Funktionsprototyp für die importierte Funktion ein, und wenden Sie das MarshalAs-Attribut auf die Parameter oder den Rückgabewert an. Im folgenden Beispiel wird ein API-Aufruf, der den Typ void* erwartet, als AsAny gemarshallt:
Declare Sub SetData Lib "..\LIB\UnmgdLib.dll" ( _ ByVal x As Short, _ <MarshalAsAttribute(UnmanagedType.AsAny)> _ ByVal o As Object)
API-Aufrufe mit "DllImport"
Das DllImport-Attribut bietet eine zweite Möglichkeit, Funktionen in DLLs ohne Typbibliotheken aufzurufen. DllImport entspricht ungefähr der Verwendung einer Declare-Anweisung, es lässt sich damit aber die Art des Funktionsaufrufs besser steuern.
Sie können DllImport bei fast allen Windows-API-Aufrufen verwenden, sofern der Aufruf einer freigegebenen (auch als static bezeichneten) Methode gilt. Sie können keine Methoden verwenden, die eine Instanz einer Klasse verlangen. Im Gegensatz zu Declare-Anweisungen kann bei DllImport-Aufrufen nicht das MarshalAs-Attribut verwendet werden.
So rufen Sie eine Windows-API mit dem DllImport-Attribut auf
Öffnen Sie ein neues Windows-Anwendungsprojekt, indem Sie im Menü Datei erst auf Neu und dann auf Projekt klicken. Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie in der Liste der Visual Basic-Projektvorlagen Windows-Anwendung aus. Das neue Projekt wird angezeigt.
Fügen Sie dem Startformular die Schaltfläche Button2 hinzu.
Doppelklicken Sie auf Button2, um die Codeansicht für das Formular anzuzeigen.
Um den Zugriff auf DllImport zu vereinfachen, fügen Sie am Anfang des Codes für die Startformularklasse eine Imports-Anweisung ein:
Imports System.Runtime.InteropServices
Deklarieren Sie vor der End Class-Anweisung des Formulars eine leere Funktion mit dem Namen MoveFile.
Weisen Sie der Funktionsdeklaration den Public-Modifizierer und den Shared-Modifizierer zu, und legen Sie, entsprechend den von der Windows-API-Funktion verwendeten Argumenten, Parameter für MoveFile fest:
Public Shared Function MoveFile( _ ByVal src As String, _ ByVal dst As String) _ As Boolean ' Leave the body of the function empty. End Function
Die Funktion kann jeden gültigen Prozedurnamen besitzen. Das DllImport-Attribut gibt den Namen in der DLL an. Es behandelt auch das Interop-Marshalling für die Parameter und Rückgabewerte, sodass Sie Visual Studio-Datentypen wählen können, die mit den von der API verwendeten Datentypen übereinstimmen.
Weisen Sie der leeren Funktion das DllImport-Attribut zu. Der erste Parameter ist der Name und der Speicherort der DLL mit der aufzurufenden Funktion. Sie brauchen den Pfad zu Dateien in Windows-Systemverzeichnissen nicht anzugeben. Der zweite Parameter ist ein benanntes Argument, das den Namen der Funktion in der Windows-API angibt. In diesem Beispiel erzwingt das DllImport-Attribut, dass Aufrufe von MoveFile an MoveFileW in KERNEL32.DLL weitergeleitet werden. Die MoveFileW-Methode kopiert eine Datei aus dem Pfad src in den Pfad dst.
<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 die Datei Test.txt, und speichern Sie diese auf der Festplatte im Verzeichnis C:\Tmp. Erstellen Sie ggf. 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" wird angezeigt, sofern die Datei verschoben werden kann.
Siehe auch
Konzepte
Erstellen von Prototypen in verwaltetem Code