Erstellen von Prototypen in verwaltetem CodeCreating Prototypes in Managed Code

In diesem Thema wird der Zugriff auf nicht verwaltete Funktionen beschrieben. Zudem werden verschiedene Attributfelder eingeführt, die die Methodendefinition in verwaltetem Code mit Anmerkungen versehen.This topic describes how to access unmanaged functions and introduces several attribute fields that annotate method definition in managed code. Beispiele für die Vorgehensweise beim Erstellen von .NET-basierten Deklarationen, die mit dem Plattformaufruf verwendet werden können, finden Sie unter Marshaling Data with Platform Invoke (Marshallen von Daten mit Plattformaufruf).For examples that demonstrate how to construct .NET-based declarations to be used with platform invoke, see Marshaling Data with Platform Invoke.

Bevor Sie auf eine nicht verwaltete DLL-Funktion in verwaltetem Code zugreifen können, müssen Sie den Namen der Funktion sowie den Namen der DLL kennen, die diese exportiert.Before you can access an unmanaged DLL function from managed code, you need to know the name of the function and the name of the DLL that exports it. Mit diesen Informationen können Sie damit beginnen, die verwaltete Definition für eine nicht verwaltete Funktion zu schreiben, die in einer DLL implementiert ist.With this information, you can begin to write the managed definition for an unmanaged function that is implemented in a DLL. Darüber hinaus können Sie die Art und Weise anpassen, in der die Funktion durch Plattformaufrufe erstellt wird und die Daten zur und von der Funktion gemarshallt werden.Furthermore, you can adjust the way that platform invoke creates the function and marshals data to and from the function.

Hinweis

Mit Funktionen der Windows-API, die eine Zeichenfolge zuordnen, können Sie die Zeichenfolge mithilfe einer Methode wie z.B. LocalFree freigeben.Windows API functions that allocate a string enable you to free the string by using a method such as LocalFree. Der Plattformaufruf behandelt solche Parameter unterschiedlich auf andere Weise.Platform invoke handles such parameters differently. Für Plattformaufrufe verwenden Sie einen Parameter vom Typ IntPtr anstelle des Typs String.For platform invoke calls, make the parameter an IntPtr type instead of a String type. Verwenden Sie von der System.Runtime.InteropServices.Marshal-Klasse bereitgestellte Methoden, um den Typ manuell in eine Zeichenfolge zu konvertieren und die Zeichenfolge dann manuell freizugeben.Use methods that are provided by the System.Runtime.InteropServices.Marshal class to convert the type to a string manually and free it manually.

Grundlagen der DeklarationDeclaration Basics

Verwaltete Definitionen für nicht verwaltete Funktionen hängen von der Sprache ab, wie Sie in den folgenden Beispielen erkennen können.Managed definitions to unmanaged functions are language-dependent, as you can see in the following examples. Ausführlichere Codebeispiele finden Sie unter Beispiele für Plattformaufrufe.For more complete code examples, see Platform Invoke Examples.

Friend Class NativeMethods
    Friend Declare Auto Function MessageBox Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
End Class

Um die Felder DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError oder DllImportAttribute.ThrowOnUnmappableChar auf eine Visual Basic-Deklaration anzuwenden, müssen Sie das DllImportAttribute-Attribut anstelle der Declare-Anweisung verwenden.To apply the DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError, or DllImportAttribute.ThrowOnUnmappableChar fields to a Visual Basic declaration, you must use the DllImportAttribute attribute instead of the Declare statement.

Imports System.Runtime.InteropServices

Friend Class NativeMethods
    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Friend Shared Function MessageBox(
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
    End Function
End Class
using System;
using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    internal static extern int MessageBox(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
using namespace System;
using namespace System::Runtime::InteropServices;

[DllImport("user32.dll")]
extern "C" int MessageBox(
    IntPtr hWnd, String* lpText, String* lpCaption, unsigned int uType);

Anpassen der DefinitionAdjusting the Definition

Attributfelder müssen unabhängig davon, ob Sie sie explizit festlegen, das Verhalten von verwaltetem Code definieren.Whether you set them explicitly or not, attribute fields are at work defining the behavior of managed code. Der Plattformaufruf arbeitet gemäß den für verschiedene Felder festgelegten Standardwerten, die als Metadaten in einer Assembly vorhanden sind.Platform invoke operates according to the default values set on various fields that exist as metadata in an assembly. Sie können dieses Standardverhalten ändern, indem Sie die Werte von mindestens einem Feld anpassen.You can alter this default behavior by adjusting the values of one or more fields. In vielen Fällen verwenden Sie das DllImportAttribute, um einen Wert festzulegen.In many cases, you use the DllImportAttribute to set a value.

In der folgenden Tabelle ist der vollständige Satz an Attributfeldern aufgeführt, die den Plattformaufruf betreffen.The following table lists the complete set of attribute fields that pertain to platform invoke. Für jedes Feld enthält die Tabelle den Standardwert und einen Link zu Informationen darüber, wie diese Felder zum Definieren nicht verwalteter DLL-Funktionen verwendet werden.For each field, the table includes the default value and a link to information on how to use these fields to define unmanaged DLL functions.

FeldField BeschreibungDescription
BestFitMapping Aktiviert oder deaktiviert die Zuordnung mit ähnlichen Zeichen.Enables or disables best-fit mapping.
CallingConvention Gibt die Aufrufkonvention an, die bei der Übergabe von Methodenargumenten verwendet wird.Specifies the calling convention to use in passing method arguments. Der Standardwert ist WinAPI, was dem __stdcall für Intel-basierte 32-Bit-Plattformen entspricht.The default is WinAPI, which corresponds to __stdcall for the 32-bit Intel-based platforms.
CharSet Die Namenszerlegung für Steuerelemente und die Art und Weise, in der Zeichenfolgenargumente an die Funktion gemarshallt werden sollen.Controls name mangling and the way that string arguments should be marshaled to the function. Der Standardwert ist CharSet.Ansi.The default is CharSet.Ansi.
EntryPoint Gibt den aufzurufenden DLL-Einstiegspunkt an.Specifies the DLL entry point to be called.
ExactSpelling Kontrolliert, ob ein Einstiegspunkt geändert werden muss, um dem Zeichensatz zu entsprechen.Controls whether an entry point should be modified to correspond to the character set. Der Standardwert variiert je nach Programmiersprache.The default value varies by programming language.
PreserveSig Kontrolliert, ob die verwaltete Methodensignatur in eine nicht verwaltete Signatur transformiert werden soll, die ein HRESULT zurückgibt und über ein zusätzliches [out, retval]-Argument für den Rückgabewert verfügt.Controls whether the managed method signature should be transformed into an unmanaged signature that returns an HRESULT and has an additional [out, retval] argument for the return value.

Der Standardwert ist true (die Signatur wird nicht transformiert).The default is true (the signature should not be transformed).
SetLastError Ermöglicht dem Aufrufer die Verwendung der Marshal.GetLastWin32Error-API-Funktion zur Ermittlung, ob beim Ausführen der Methode ein Fehler aufgetreten ist.Enables the caller to use the Marshal.GetLastWin32Error API function to determine whether an error occurred while executing the method. In Visual Basic ist der Standardwert true In C# und C++ ist der Standardwert false.In Visual Basic, the default is true; in C# and C++, the default is false.
ThrowOnUnmappableChar Steuert das Auslösen einer Ausnahme bei einem nicht zuzuordnenden Unicode-Zeichen, das in ein ANSI-Zeichen ("?") konvertiert wird.Controls throwing of an exception on an unmappable Unicode character that is converted to an ANSI "?" character.

Detaillierte Verweisinformationen finden Sie unter DllImportAttribute.For detailed reference information, see DllImportAttribute.

Überlegungen zur PlattformaufrufsicherheitPlatform invoke security considerations

Die Member Assert, Deny und PermitOnly der SecurityAction-Enumeration werden als stack walk modifier (Stackwalkmodifizierer) bezeichnet.The Assert, Deny, and PermitOnly members of the SecurityAction enumeration are referred to as stack walk modifiers. Diese Member werden ignoriert, wenn sie als deklarative Attribute für Deklarationen von Plattformaufrufen und COM-IDL-Anweisungen (Interface Definition Language) verwendet werden.These members are ignored if they are used as declarative attributes on platform invoke declarations and COM Interface Definition Language (IDL) statements.

Beispiele für PlattformaufrufePlatform Invoke Examples

Die Beispiele zum Plattformaufruf in diesem Abschnitt veranschaulichen die Verwendung des RegistryPermission-Attributs mit den Stapelmodifizierern.The platform invoke samples in this section illustrate the use of the RegistryPermission attribute with the stack walk modifiers.

Im folgenden Beispiel werden die Modifizierer SecurityAction,Assert, Deny und PermitOnly ignoriert.In the following example, the SecurityActionAssert, Deny, and PermitOnly modifiers are ignored.

[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionAssert();  
  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  
  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  

Der Demand-Modifizierer im folgenden Beispiel wird jedoch akzeptiert.However, the Demand modifier in the following example is accepted.

[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  

SecurityAction-Modifizierer funktionieren ordnungsgemäß, wenn sie in einer Klasse positioniert werden, die den Plattformaufruf enthält (umschließt).SecurityAction modifiers do work correctly if they are placed on a class that contains (wraps) the platform invoke call.

      [RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
public ref class PInvokeWrapper  
{  
public:  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
};  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
class PInvokeWrapper  
{  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
}  

SecurityAction-Modifizierer funktionieren auch in einem geschachtelten Szenario ordnungsgemäß, in dem sie im Aufrufer des Plattformaufrufs positioniert werden:SecurityAction modifiers also work correctly in a nested scenario where they are placed on the caller of the platform invoke call:

      {  
public ref class PInvokeWrapper  
public:  
    [DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
  
    [RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    public static bool CallRegistryPermission()  
    {  
     return CallRegistryPermissionInternal();  
    }  
};  
class PInvokeScenario  
{  
    [DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionInternal();  
  
    [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    public static bool CallRegistryPermission()  
    {  
     return CallRegistryPermissionInternal();  
    }  
}  

Beispiele zu COM-InteropCOM Interop Examples

Die Beispiele zu COM-Interop in diesem Abschnitt veranschaulichen die Verwendung des RegistryPermission-Attributs mit den Stapelmodifizierern.The COM interop samples in this section illustrate the use of the RegistryPermission attribute with the stack walk modifiers.

Die folgenden Deklarationen der COM-Interop-Schnittstelle ignorieren die Modifizierer Assert, Deny und PermitOnly auf ähnliche Weise wie die Beispiele zum Plattformaufruf im vorherigen Abschnitt.The following COM interop interface declarations ignore the Assert, Deny, and PermitOnly modifiers, similarly to the platform invoke examples in the previous section.

[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IAssertStubsItf  
{  
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  
  
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IDenyStubsItf  
{  
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  
  
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IAssertStubsItf  
{  
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  

Darüber hinaus wird der Demand-Modifizierer nicht in Deklarationsszenarien der COM-Interop-Schnittstelle akzeptiert, wie im folgenden Beispiel veranschaulicht.Additionally, the Demand modifier is not accepted in COM interop interface declaration scenarios, as shown in the following example.

[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IDemandStubsItf  
{  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  

Siehe auchSee also