Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette rubrique explique comment accéder aux fonctions non managées et présente plusieurs champs d’attribut qui annotent la définition de méthode dans le code managé. Pour obtenir des exemples montrant comment construire des déclarations .NET à utiliser avec un appel de code non managé, consultez Marshaling de données avec un appel de code non managé.
Avant de pouvoir accéder à une fonction DLL non managée à partir du code managé, vous devez connaître le nom de la fonction et le nom de la DLL qui l’exporte. Avec ces informations, vous pouvez commencer à écrire la définition managée pour une fonction non managée implémentée dans une DLL. En outre, vous pouvez ajuster la façon dont l'appel de code non managé crée la fonction et marshale les données vers et depuis la fonction.
Remarque
Les fonctions d’API Windows qui allouent une chaîne vous permettent de libérer la chaîne à l’aide d’une méthode telle que LocalFree
. L’appel de plateforme gère ces paramètres différemment. Pour les appels de plateforme, définissez le paramètre comme un type IntPtr
au lieu d’un type String
. Utilisez des méthodes fournies par la System.Runtime.InteropServices.Marshal classe pour convertir le type en chaîne manuellement et le libérer manuellement.
Principes de base de la déclaration
Les définitions managées pour les fonctions non managées dépendent du langage, comme vous pouvez le voir dans les exemples suivants. Pour obtenir des exemples de code plus complets, consultez Exemples d’appel de plateforme.
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
Pour appliquer les champs DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError ou DllImportAttribute.ThrowOnUnmappableChar à une déclaration Visual Basic, vous devez utiliser l’attribut DllImportAttribute au lieu de l’instruction Declare
.
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);
Ajustement de la définition
Que vous les définissez explicitement ou non, les champs d’attribut sont au travail définissant le comportement du code managé. L’appel de plateforme fonctionne en fonction des valeurs par défaut définies sur différents champs qui existent en tant que métadonnées dans un assembly. Vous pouvez modifier ce comportement par défaut en ajustant les valeurs d’un ou plusieurs champs. Dans de nombreux cas, vous utilisez le DllImportAttribute pour définir une valeur.
Le tableau suivant répertorie l’ensemble complet de champs d’attributs relatifs à l’appel de plateforme. Pour chaque champ, la table inclut la valeur par défaut et un lien vers des informations sur l’utilisation de ces champs pour définir des fonctions DLL non managées.
Terrain | Descriptif |
---|---|
BestFitMapping | Active ou désactive le mappage le mieux adapté. |
CallingConvention | Spécifie la convention d’appel à utiliser pour passer des arguments de méthode. La valeur par défaut est WinAPI , qui correspond à __stdcall pour les plateformes 32 bits à base d'Intel. |
CharSet | Contrôle la décoration des noms et la façon dont les arguments de chaîne doivent être marshalés vers la fonction. La valeur par défaut est CharSet.Ansi . |
EntryPoint | Spécifie le point d’entrée DLL à appeler. |
ExactSpelling | Contrôle si un point d’entrée doit être modifié pour correspondre au jeu de caractères. La valeur par défaut varie selon le langage de programmation. |
PreserveSig | Contrôle si la signature de méthode managée doit être transformée en une signature non managée qui retourne un HRESULT et a un argument supplémentaire [out, retval] pour la valeur de retour. La valeur par défaut est true (la signature ne doit pas être transformée). |
SetLastError | Permet à l’appelant d’utiliser la Marshal.GetLastWin32Error fonction API pour déterminer si une erreur s’est produite lors de l’exécution de la méthode. En Visual Basic, la valeur par défaut est true ; en C# et C++, la valeur par défaut est false . |
ThrowOnUnmappableChar | Contrôle la levée d'une exception sur un caractère Unicode non mappable converti en un caractère ANSI "?". |
Pour obtenir des informations de référence détaillées, consultez DllImportAttribute.
Considérations relatives à la sécurité des appels de code non managé
Les membres Assert
, Deny
et PermitOnly
de l’énumération SecurityAction sont appelés modificateurs de parcours de pile. Ces membres sont ignorés s'ils sont utilisés comme des attributs déclaratifs sur des déclarations d'appel de code non managé et des instructions Interface Definition Language (IDL) COM.
Exemples d'appel de code non managé
Les exemples d'appel de code non managé de cette section illustrent l'utilisation de l'attribut RegistryPermission
avec les modificateurs de parcours de pile.
Dans l’exemple suivant, les modificateurs SecurityActionAssert
, Deny
, et PermitOnly
sont ignorés.
[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();
Toutefois, le Demand
modificateur de l’exemple suivant est accepté.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction Les modificateurs fonctionnent correctement s’ils sont placés sur une classe qui contient (encapsule) l'appel de plateforme.
[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();
}
Les modificateurs SecurityAction fonctionnent également correctement dans un scénario d’imbrication dans lequel ils sont placés sur l’appelant de l’appel de code non managé :
{
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();
}
}
Exemples d’interopérabilité COM
Les exemples COM Interop de cette section illustrent l'utilisation de l'attribut RegistryPermission
avec les modificateurs de parcours de pile.
Les déclarations d’interface COM interop suivantes ignorent les modificateurs Assert
, Deny
, et PermitOnly
, de la même façon que les exemples d'appel de plateforme dans la section précédente.
[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();
}
En outre, le Demand
modificateur n’est pas accepté dans les scénarios de déclaration d’interface COM Interop, comme illustré dans l’exemple suivant.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}
Voir aussi
- Utilisation de Fonctions DLL Non Managées
- Spécification d’un point d’entrée
- Spécification d’un jeu de caractères
- Exemples d’appel de code non managé
- Considérations relatives à la sécurité des appels de code non managé
- Identification des fonctions dans les DLL
- Création d’une classe pour contenir des fonctions DLL
- Appel à une fonction DLL