Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se describe cómo acceder a funciones no administradas e introduce varios campos de atributo que anotan la definición del método en código administrado. Para ver ejemplos que muestran cómo construir declaraciones basadas en .NET que se utilizarán con la invocación de plataforma, consulte Marshalling Data with Platform Invoke.
Para poder acceder a una función DLL no administrada desde código administrado, debe conocer el nombre de la función y el nombre del archivo DLL que lo exporta. Con esta información, puede empezar a escribir la definición administrada para una función no administrada que se implementa en un archivo DLL. Además, puede ajustar la manera en que la invocación de plataforma crea la función y calcula las referencias de los datos desde y hacia la función.
Nota:
Las funciones de la API de Windows que asignan una cadena permiten liberar la cadena mediante un método como LocalFree
. La invocación de plataforma controla estos parámetros de forma diferente. Para las llamadas de invocación de plataforma, haga que el parámetro sea del tipo IntPtr
en lugar del tipo String
. Use métodos proporcionados por la System.Runtime.InteropServices.Marshal clase para convertir el tipo en una cadena manualmente y liberarlo manualmente.
Conceptos básicos de declaración
Las definiciones administradas para funciones no administradas dependen del lenguaje, como puede ver en los ejemplos siguientes. Para obtener ejemplos de código más completos, consulte Ejemplos de invocación de plataforma.
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
Para aplicar los campos DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError o DllImportAttribute.ThrowOnUnmappableChar a una declaración de Visual Basic, debe usar el atributo DllImportAttribute en lugar de la instrucción 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);
Ajustar la definición
Tanto si los establece explícitamente como si no, los campos de atributo funcionan definiendo el comportamiento del código administrado. La invocación de plataforma funciona según los valores predeterminados establecidos en varios campos que existen como metadatos en un ensamblado. Puede modificar este comportamiento predeterminado ajustando los valores de uno o varios campos. En muchos casos, se usa DllImportAttribute para establecer un valor.
En la tabla siguiente se muestra el conjunto completo de campos de atributo que pertenecen a la invocación de plataforma. Para cada campo, la tabla incluye el valor predeterminado y un vínculo a información sobre cómo usar estos campos para definir funciones DLL no administradas.
Campo | Descripción |
---|---|
BestFitMapping | Habilita o deshabilita la asignación con ajuste perfecto. |
CallingConvention | Especifica la convención de llamada que se va a usar para pasar argumentos de método. El valor predeterminado es WinAPI , que corresponde a __stdcall para las plataformas basadas en Intel de 32 bits. |
CharSet | Controla la eliminación de nombres y la forma en que deben serializarse los argumentos de cadena en la función. El valor predeterminado es CharSet.Ansi . |
EntryPoint | Especifica el punto de entrada DLL al que se debe llamar. |
ExactSpelling | Controla si se debe modificar un punto de entrada para que se corresponda con el juego de caracteres. El valor predeterminado varía según el lenguaje de programación. |
PreserveSig | Controla si la firma del método administrado debería transformarse en una firma no administrada que devuelve un resultado HRESULT y tiene un argumento adicional [out, retval] para el valor devuelto. El valor predeterminado es true (la firma no se debe transformar). |
SetLastError | Permite al autor de la llamada usar la Marshal.GetLastWin32Error función de API para determinar si se produjo un error al ejecutar el método . En Visual Basic, el valor predeterminado es true ; en C# y C++, el valor predeterminado es false . |
ThrowOnUnmappableChar | Controla el inicio de una excepción cuando un carácter Unicode que no se puede asignar se convierte en un carácter ANSI "?". |
Para obtener información de referencia detallada, vea DllImportAttribute.
Consideraciones sobre la seguridad de la invocación de plataforma
Los miembros Assert
, Deny
y PermitOnly
de la enumeración SecurityAction se conocen como modificadores del recorrido de la pila. Estos miembros se omiten si se usan como atributos declarativos en declaraciones de invocación de plataforma e instrucciones del lenguaje de definición de interfaz (IDL) COM.
Ejemplos de invocación de plataforma
Los ejemplos de invocación de plataforma de esta sección muestran el uso del atributo RegistryPermission
con los modificadores del recorrido de la pila.
En el ejemplo siguiente, se omiten los SecurityActionAssert
modificadores , Deny
y PermitOnly
.
[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();
Sin embargo, el modificador Demand
se acepta en el siguiente ejemplo.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction Los modificadores funcionan correctamente si se colocan en una clase que contiene (encapsula) la llamada de invocación de plataforma.
[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();
}
Los modificadores SecurityAction también funcionan correctamente en un escenario anidado en el que se colocan en el llamador de la llamada de invocación de plataforma:
{
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();
}
}
Ejemplos de interoperabilidad COM
Los ejemplos de interoperabilidad COM de esta sección muestran el uso del atributo RegistryPermission
con los modificadores del recorrido de la pila.
Las siguientes declaraciones de interfaz de interoperabilidad COM ignoran los modificadores Assert
, Deny
y PermitOnly
, de forma similar a los ejemplos de llamada de plataforma de la sección anterior.
[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();
}
Además, el Demand
modificador no se acepta en escenarios de declaración de interfaz de interoperabilidad COM, como se muestra en el ejemplo siguiente.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}
Consulte también
- consumo de funciones DLL no administradas
- Especificar un punto de entrada
- Especificar un conjunto de caracteres
- Ejemplos de invocación de plataforma
- Consideraciones sobre la seguridad de la invocación de plataforma
- Identificación de funciones en archivos DLL
- Creación de una clase para contener funciones DLL
- Llamada a una función DLL