Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit onderwerp wordt beschreven hoe u toegang krijgt tot niet-beheerde functies en een aantal kenmerkvelden introduceert die aantekeningen toevoegen aan de methodedefinitie in beheerde code. Voor voorbeelden die laten zien hoe u .NET-gebaseerde declaraties kunt opstellen voor gebruik met platformaanroepen, zie Marshalling Data with Platform Invoke.
Voordat u toegang hebt tot een niet-beheerde DLL-functie vanuit beheerde code, moet u de naam van de functie en de naam van de DLL die deze exporteert, weten. Met deze informatie kunt u beginnen met het schrijven van de beheerde definitie voor een niet-beheerde functie die is geïmplementeerd in een DLL. Bovendien kunt u de manier aanpassen waarop het platform de functie aanroept en gegevens naar en van de functie organiseert.
Opmerking
Met Windows API-functies waarmee een tekenreeks wordt toegewezen, kunt u de tekenreeks vrijmaken met behulp van een methode zoals LocalFree. Platform roept dergelijke parameters anders aan. Voor platformaanroepen moet u de parameter van het type IntPtr maken in plaats van het type String. Gebruik methoden die door de System.Runtime.InteropServices.Marshal klasse worden geleverd om het type handmatig te converteren naar een tekenreeks en deze handmatig vrij te maken.
Basisbeginselen van declaratie
Beheerde definities voor niet-beheerde functies zijn taalafhankelijk, zoals u kunt zien in de volgende voorbeelden. Zie Voorbeelden van platform invoke voor meer volledige codevoorbeelden.
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
Als u de DllImportAttribute.BestFitMappingvelden , DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpellingof DllImportAttribute.PreserveSigDllImportAttribute.SetLastErrorDllImportAttribute.ThrowOnUnmappableChar velden wilt toepassen op een Visual Basic-declaratie, moet u het DllImportAttribute kenmerk gebruiken in plaats van de Declare instructie.
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);
De definitie aanpassen
Of u deze nu expliciet instelt of niet, kenmerkvelden werken aan het definiëren van het gedrag van beheerde code. Het aanroepen van het platform werkt volgens de standaardwaarden die zijn ingesteld op verschillende velden die bestaan als metagegevens in een assembly. U kunt dit standaardgedrag wijzigen door de waarden van een of meer velden aan te passen. In veel gevallen gebruikt u de DllImportAttribute functie om een waarde in te stellen.
De volgende tabel bevat de volledige set kenmerkvelden die betrekking hebben op het aanroepen van het platform. Voor elk veld bevat de tabel de standaardwaarde en een koppeling naar informatie over het gebruik van deze velden om onbeheerde DLL-functies te definiëren.
| Veld | Beschrijving |
|---|---|
| BestFitMapping | Schakelt best-fit mapping in of uit. |
| CallingConvention | Hiermee geeft u de aanroepconventie op die moet worden gebruikt bij het doorgeven van methodeargumenten. De standaardwaarde is WinAPI, die overeenkomt met __stdcall de 32-bits Intel-platforms. |
| CharSet | Regelt het wijzigen van namen en de manier waarop string-argumenten naar de functie worden doorgegeven. De standaardwaarde is CharSet.Ansi. |
| EntryPoint | Hiermee specificeert u het DLL-toegangspunt dat moet worden aangeroepen. |
| ExactSpelling | Hiermee bepaalt u of een toegangspunt moet worden gewijzigd zodat deze overeenkomt met de tekenset. De standaardwaarde verschilt per programmeertaal. |
| PreserveSig | Hiermee bepaalt u of de handtekening van de beheerde methode moet worden omgezet in een niet-beheerde handtekening die een HRESULT retourneert en een extra argument [out, retval] voor de retourwaarde heeft. De standaardwaarde is true (de handtekening mag niet worden getransformeerd). |
| SetLastError | Hiermee kan de aanroeper de Marshal.GetLastWin32Error API-functie gebruiken om te bepalen of er een fout is opgetreden tijdens het uitvoeren van de methode. In Visual Basic is de standaardwaarde true; in C# en C++ is de standaardwaarde false. |
| ThrowOnUnmappableChar | Regelt het genereren van een uitzondering bij een niet-mapbaar Unicode-teken dat wordt omgezet naar een ANSI '?' teken. |
Zie voor gedetailleerde naslaginformatie DllImportAttribute.
Beveiligingsoverwegingen voor platform aanroepen
De Assert, Denyen PermitOnly leden van de SecurityAction opsomming worden stack walk modifiers genoemd. Deze leden worden genegeerd als ze worden gebruikt als declaratieve kenmerken op platformaanroepen en IDL-instructies (COM Interface Definition Language).
Voorbeelden van Platforminvoke
Het platform roept voorbeelden in deze sectie aan om het gebruik van het RegistryPermission kenmerk te illustreren met de stack walk-modifiers.
In het volgende voorbeeld worden de SecurityActionAssert, Denyen PermitOnly modifiers genegeerd.
[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();
De Demand wijzigingsfunctie in het volgende voorbeeld wordt echter geaccepteerd.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction modifiers werken correct als ze op een klasse worden geplaatst die het aanroepen van het platform omvat (omsluit).
[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 modifiers werken ook correct in een genest scenario waarin ze worden geplaatst op de aanroeper van het platform:
{
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();
}
}
Voorbeelden van COM-interoperabiliteit
De COM-interoperabiliteitsvoorbeelden in deze sectie illustreren het gebruik van het RegistryPermission kenmerk met de stack walk-modifiers.
De volgende COM interop interfacedeclaraties negeren de Assert, Deny, en PermitOnly modifiers, vergelijkbaar met de platform-invoke voorbeelden in de vorige sectie.
[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();
}
Bovendien wordt de Demand modifier niet geaccepteerd in COM-interop interfaceverklaringen, als in het volgende voorbeeld.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}